《C++ GUI Qt 4 編程》 筆記(一)

博客搬家自 http://zhouyuanchao.com/wordpress/archives/62


第一部分 Qt基礎

#include <QApplication>
#include <QLabel>
int main(int argc, char* argv[])
{
	QApplication app(argc, argv);
	QLabel* label = new QLabel("Hello Qt!");
	label->show();
	return app.exec();
}
// 信號和槽
#include <QApplication>
#include <QPushButton>
int main(int argc, char* argv[])
{
	QApplication app(argc, argv);
	QPushButton* button = new QPushButton("Quit");
	QObject::connect(button, SIGNAL(clicked()),
		&app, SLOT(quit()));
	button.show();
	return app.exec();
}

佈局管理器
QHBoxLayout
QVBoxLayout
QGridLayout

1. 聲明所需的窗口部件
2. 設置所應具備的屬性
3. 添加到佈局中
4. 連接信號和槽

對於定義了信號和槽的類,在類定義開始處的Q_OBJECT宏都是必需的。

class FindDialog : public QDialog
{
	Q_OBJECT
public:
	FindDialog(QWidget* parent = 0);

	// signals關鍵字實際上是一個宏
signals:
	void findNext(const QString& str, Qt::CaseSensitivity cs);
	// ...

private slots:
	void findClicked();
	// ...
}

當頭文件中只使用了對象指針時,可以使用前置聲明 比如class Fruit;

Qt模塊
QtCore
QtGui
QtNetwork
QtOpenGL
QtScript
QtSql
QtSvg
QtXml

tr("Match") // 多語言支持

label->setBuddy(lineEdit); // 按下標籤的快捷鍵時,焦點會移到lineEdit
button->setDefault(true); // 默認按鈕
rightLayout->addStretch(); // 伸展器
dialog->setFixedHeight(sizeHint())
sizeHint() 返回窗口部件的理想尺寸大小

發射信號

emit findPrevious(text, cs);

一個信號可以有多個槽,
在發射信號時,會以不確定的順序調用槽。
多個信號可以連接同一個槽。

信號可以與信號相連,發射第一個信號時,也會發射第二個信號。

移除連接
disconnect()

元對象系統
內省
即動態獲得類有哪些函數、信號、槽、成員變量
如果信號的參數比槽的參數多,多餘的參數被忽略。
這種機制可以應用於任何QObject的子類中

QIntValidator
QDoubleValidator
QRegExpValidator

動態加載ui文件

QUiLoader uiLoader; // CONFIG += uitools
QFile file("sortdialog.ui");
QWidget* sortDialog = uiLoader.load(&file);
QComboBox* primaryColumnCombo = 
sortDialog->findChild<QComboBox*>("primaryColumnCombo");

啓動畫面

QSplashScreen
QSplashScreen* splash = new QSplashScreen;
splash->setPixmap(QPixmap(":/images/splash.png"));
splash->show();
// ... load something
splash->showMessage(...);
mainWindow.show();
splash->finish(&mainWindow);
delete splash;

子類化對話框
繼承自QDialog
在構造函數中創建控件、佈局

Q_OBJECT 信號和槽、內省
Q_OBJECT 定義了某些函數聲明
moc工具生成函數定義

使用GUI設計工具
1. 創建並初始化子窗口部件
2. 把子窗口部件放到佈局中
3. 設置Tab鍵順序
4. 建立信號-槽之間的連接
5. 實現對話框中的自定義槽

uic工具會將.ui文件轉換成c++

創建一個新類MyDialog從QDialog和Ui::MyDialog中繼承,並且由它來實現那些缺失的功能。

通過簡單地增加另外一個間接層就可以解決軟件的任何問題。

setupUi()自動建立信號連接
槽命名規則 on_objectName_signalName() e.g. on_lineEdit_textChanged()

需要明確刪除的對象是那些使用new創建的並且沒有父對象的對象。

layout()->setSizeConstraint(QLayout::SetFixedSize);

內置窗口部件類和對話框類
QMenuBar
QToolBar
QStatusBar
QSplitter
QScrollArea
QPushButton QToolButton QCheckBox QRadioButton
QGroupBox QFrame
QTabWidget QToolBox
QAbstractScrollArea
QListView QTreeView QTableView
QLabel
QLCDNumber
QProgressBar
QTextBrowser
QLineEdit QTextEdit
QSpinBox QDoubleSpinBox QComboBox QDateEdit
QTimeEdit QDateTimeEdit QScrollBar QSlider QDial
QInputDialog
QProgressDialog
QMessageBox
QErrorMessage
QColorDialog
QFontDialog
QPageSetupDialog
QFileDialog
QPrintDialog
QFontComboBox
QWizard

closeEvent() 函數是QWidget類中的一個虛函數
當用戶關閉窗口時,這個函數會被自動調用。

setCentralWidget()
中央窗口部件會佔用主窗口的中央區域部分。

QWidget::setWindowIcon()

Qt資源機制
資源文件(xml) xxx.qrc

<RCC>
	<qresource>
		<file>images/icon.png</file>
		...
	</qresource>
</RCC>

.pro 中 RESOURCES = xxx.qrc
所有資源文件都會編譯到應用程序的可執行文件中。
引用資源 :/images/icon.png

動作 Action
一個動作就是一個可以添加到任意數量的菜單和工具欄上的項。

創建菜單和工具欄的步驟:
1. 創建並且設置動作
2. 創建菜單並且把動作添加到菜單上
3. 創建工具欄並且把動作添加到工具欄上

newAction = new QAction(tr("&New"), this);
newAction->setIcon(QIcon(":/images/new.png"));
newAction->setShortcut(QKeySequence::New); // exitAction->setShortcut(tr("Ctrl+Q"));
newAction->setStatusTip(tr("Create a new spreadsheet file"));
connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));
// 複選動作
newAction->setCheckable(true);
newAction->setChecked(true);

使用QActionGroup,可以實現互相排斥的複選動作

QApplication對象的aboutQt()槽

// QMainWindow::menuBar()返回一個指向QMenuBar的指針,
// 菜單欄會在第一次調用menuBar()函數的時候就創建出來。
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(newAction);
fileMenu->addAction(openAction);
separatorAction = fileMenu->addSeparator();

任何Qt窗口部件都可以有一個與之相關聯的QActions列表。要爲該應用程序提供一個上下文菜單,可以將所需要的動作添加到窗口部件中,並且將那個窗口部件的上下文菜單策略(context menu policy)設置爲一個現實這些動作的上下文菜單。

spreadsheet->addAction(cutAction);
spreadSheet->addAction(copyAction);
spreadSheet->addAction(pasteAction);
spreadSheet->setContextMenuPolicy(Qt::ActionsContextMenu);

一種更爲高級的提供上下文菜單方法是重新實現QWidget::contextMenuEvent()函數,創建一個QMenu窗口部件,在其中添加所期望的那些動作,並且再對該窗口部件調用exec()函數。

// 工具欄
fileToolBar = addToolBar(tr("&File"));
fileToolBar->addAction(newAction);
editToolBar = addToolBar(tr("&Edit"));
editToolBar->addAction(cutAction);
editToolBar->addSeparator();
// 狀態欄
locationLabel = new QLabel(" W999 ");
locationLabel->setAlignment(Qt::AlignHCenter);
locationLabel->setMinimumSize(locationLabel->sizeHint());
formulaLabel = new QLabel;
formulaLabel->setIndent(3);
statusBar()->addWidget(locationLabel);
statusBar()->addWidget(formulaLabel, 1); // 第二個參數 窗口大小改變時是否伸展

QMessageBox::warning(parent, title, message, buttons);
QMessageBox::information()

QFileDialog::getOpenFileName()
QFileDialog::getSaveFileName()

// 狀態欄顯示一個2秒的信息
statusBar()->showMessage(tr("File loaded"), 2000);

QMessageBox::question()
QMessageBox::critical()

當最後一個窗口關閉後,應用程序就結束了。
通過把QApplication的quitOnLastWindowClosed屬性設置爲false,應用程序將會持續保持運行,直到調用QApplication::quit()函數,程序纔會結束。

QFileInfo(fullFileName).fileName();

每個QWidget都有一個windowModified屬性,如果該窗口的文檔存在沒有保存的變化,則應當把它設置爲true,否則應當設爲false。window未保存的文件名後跟一個星號,mac使用另外的方式,Qt會自動處理。只需讓windowModified屬性保持當前最新狀態,並且當需要顯示星號的時候將"[*]"放在窗口的標題欄上即可。

// 使用參數替換%n
tr("%1[*] - %2").arg(shownName).arg(tr("Spreadsheet"))
showName + tr("[*] - Spreadsheet");

// QStringList recentFiles
QMutableStringListIterator i(recentFiles);
while (i.hasNext)
{
	if (!QFile::exits(i.next()))
	i.remove();
}

每個動作(action)都可以帶一個與之相關的QVariant,setData()

在槽中,使用QObject::sender()查出是哪個特有動作調用了這個槽。

QAction* action = qobject_cast<QAction*>(sender());
if (action)
	// ...

qobject_cast<T>() 與 dynamic_cast<T>()不同的是,可正確地跨越動態庫邊界。

非模態對話框
show() 顯示
raise() 稱爲頂層窗口
activateWindow() 激活狀態

模態對話框
show() setModal()
-or-
// exec()返回值
// true QDialog::Accepted
// false QDialog::Rejected
exec()

QString str;
str.mid(1).toInt();
str[0].unicode() - 'A';
QMessageBox::about(this, tr("About Spreadsheet"),
	tr("<h2>Spreadsheet 1.1</h2>"
	   "<p>Copyright &copy; 2008 Software Inc.</p>"));

QSettings類
windows 註冊表
unix 文本文件
mac os x Core Foundation Preferences的應用程序編程接口

QSettings settings("組織名字", "應用程序名字");
settings.setValue("geometry", ...);
settings.setValue("findDialog/matchCase", ...);
settings.beginGroup("findDialog");
settings.setValue("matchCase", ...);
settings.endGroup();

值的類型:int bool double QSetting QStringList QVariant

獲得值

settings.value("geometry").toByteArray();
settings.value("showGrid", true).toBool(); // 第二個參數:默認值

QApplication::closeAllWindows()會關閉所有應用程序的窗口。

// 默認關閉窗口只是隱藏窗口
// 以下代碼會使Qt在關閉窗口時將其刪除
QWidget::setAttribute(Qt::WA_DeleteOnClose);
// 遍歷所有主窗口
foreach (QWidget* win, QApplication::topLevelWidgets())
{
	MainWindow* mainWin = qobject_cast<MainWindow*>(win);
}

啓動畫面的作用
1. 對緩慢的啓動過程進行掩飾
2. 滿足市場部門的要求

通過對一個已經存在的Qt窗口部件進行子類化或者
直接對QWidget進行子類化,就可以創建自定義窗口部件

整數轉爲16進制

QString::number(value, 16).toUpper();
text.toInt(&ok, 16);

子類化QWidget

class IconEditor : public QWidget
{
	Q_OBJECT
	// 這些屬性將顯示在Qt設計師中
	Q_PROPERTY(QColor penColor READ penColor WRITE setPenColor)
};
QRgb red = qRgb(255, 0, 0);

QWidget::updateGeometry()
告訴包含這個窗口部件的任意佈局,這個窗口部件的大小提示已經發生改變了,於是,該佈局將會自動適應這個新的大小提示

強制產生一個繪製事件
QWidget::update() 在Qt下一次處理事件時才簡單地調用一個繪製事件
QWidget::repaint() 即時的重繪事件

每一個窗口部件都會配備一個調色板,由它來確定做什麼事應該使用什麼顏色

Qt::WA_StaticContents屬性
當重新改變窗口部件的大小時,這個窗口部件的內容並沒有發生變化,而且它的內容仍然保留從窗口部件左上角開始的特性。當重新定義窗口部件的大小時,通過使用這個信息,Qt就可以避免對已經顯示區域的重新繪製。

第三方窗口部件
GraphPak
KD Chart
Qwt

QApplication::setOverrideCursor()
QApplication::restoreOverrideCursor()


發佈了34 篇原創文章 · 獲贊 21 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章