倉庫php
- Qt 開發平臺中直接支持主窗口的概念 - QMainWindow 是 Qt 中主窗口的基類 - QMainWindow 繼承於 QWidget 是一種容器類型的組件
1. 菜單欄 2. 工具欄 3. 中心組件 4. 停靠組件 5. 狀態欄
/** *@brief 建立菜單欄 */ bool MainWindow::initMenuBar() { QMenuBar* mb = menuBar(); bool ret = (mb != nullptr); ret = ret && initFileMenu(mb); ret = ret && initEditMenu(mb); ret = ret && initFormatMenu(mb); ret = ret && initViewMenu(mb); ret = ret && initHelpMenu(mb); return ret; } /** *@brief 建立下拉菜單組 */ bool MainWindow::initFileMenu(QMenuBar* mb) { QMenu* menu = new QMenu("文件(&F)", mb); bool ret = (menu != nullptr); if( ret ) { QAction* action = nullptr; ret = ret && makeAction(action, menu, "新建(&N)", Qt::CTRL + Qt::Key_N); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFileNew())); menu->addAction(action); } ret = ret && makeAction(action, menu, "打開(&O)...", Qt::CTRL + Qt::Key_O); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFileOpen())); menu->addAction(action); } ret = ret && makeAction(action, menu, "保存(&S)", Qt::CTRL + Qt::Key_S); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFileSave())); menu->addAction(action); } ret = ret && makeAction(action, menu, "另存爲(&A)...", 0); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFileSaveAs())); menu->addAction(action); } menu->addSeparator(); ret = ret && makeAction(action, menu, "頁面設置(&U)...", Qt::CTRL + Qt::Key_U); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFilePageSetup())); menu->addAction(action); } ret = ret && makeAction(action, menu, "打印(&P)...", Qt::CTRL + Qt::Key_P); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFilePrint())); menu->addAction(action); } menu->addSeparator(); ret = ret && makeAction(action, menu, "退出(&X)", 0); if( ret ) { menu->addAction(action); } } if( ret ) { mb->addMenu(menu); } else { delete menu; } return ret; } /** *@brief 建立菜單項 */ bool MainWindow::makeAction(QAction*& action, QWidget* parent, QString text, int key) { bool ret = true; action = new QAction(text, parent); if( action != nullptr ) { action->setShortcut(QKeySequence(key)); // 添加快捷鍵 } else { ret = false; } return ret; }
/** *@brief 建立工具欄 */ bool MainWindow::initToolBar() { QToolBar* tb = addToolBar("工具欄"); bool ret = true; tb->setIconSize(QSize(16, 16)); tb->setFloatable(false); tb->setMovable(false); ret = ret && initFileToolItem(tb); tb->addSeparator(); ret = ret && initEditToolItem(tb); tb->addSeparator(); ret = ret && initFormatToolItem(tb); tb->addSeparator(); ret = ret && initViewToolItem(tb); return ret; } /** *@brief 建立與文件操做相關的快捷項 */ bool MainWindow::initFileToolItem(QToolBar* tb) { QAction* action = nullptr; bool ret = true; ret = ret && makeAction(action, tb, "新建", ":/Res/pic/new.png"); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFileNew())); tb->addAction(action); } ret = ret && makeAction(action, tb, "打開", ":/Res/pic/open.png"); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFileOpen())); tb->addAction(action); } ret = ret && makeAction(action, tb, "保存", ":/Res/pic/save.png"); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFileSave())); tb->addAction(action); } ret = ret && makeAction(action, tb, "另存爲", ":/Res/pic/saveas.png"); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFileSaveAs())); tb->addAction(action); } ret = ret && makeAction(action, tb, "打印", ":/Res/pic/print.png"); if( ret ) { connect(action, SIGNAL(triggered()), this, SLOT(onFilePrint())); tb->addAction(action); } return ret; } /** *@brief 建立具體的快捷項 */ bool MainWindow::makeAction(QAction*& action, QWidget* parent, QString tip, QString icon) { bool ret = true; action = new QAction("", parent); if( action != nullptr ) { action->setToolTip(tip); action->setIcon(QIcon(icon)); } else { ret = false; } return ret; }
狀態欄中的消息類型git
/** *@brief 建立狀態欄 */ bool MainWindow::initStatusBar() { QStatusBar* sb = statusBar(); QLabel* label = new QLabel("D.T.TianSong"); bool ret = true; if( label != nullptr ) { sb->addPermanentWidget(new QLabel()); statusLabel.setMinimumWidth(150); statusLabel.setAlignment(Qt::AlignCenter); statusLabel.setText("length: " + QString::number(0) + " lines: " + QString::number(1)); sb->addPermanentWidget(&statusLabel); statusCursorLabel.setMinimumWidth(150); statusCursorLabel.setAlignment(Qt::AlignCenter); statusCursorLabel.setText("Ln: " + QString::number(1) + " Col: " + QString::number(1)); sb->addPermanentWidget(&statusCursorLabel); label->setMinimumWidth(150); label->setAlignment(Qt::AlignCenter); sb->addPermanentWidget(label); } else { ret = false; } return ret; }
單行文本支持 | 多行文本支持 | 自定義格式支持 | 富文本支持 | |
QLineEdit | Yes | No | No | No |
QPlainTextEdit | Yes | Yes | No | No |
QTextEdit | Yes | Yes | Yes | Yes |
/** *@brief 建立中心組件 */ bool MainWindow::initMainEditor() { bool ret = true; QPalette p = mainEditor.palette(); p.setColor(QPalette::Inactive, QPalette::Highlight, p.color(QPalette::Active, QPalette::Highlight)); p.setColor(QPalette::Inactive, QPalette::HighlightedText, p.color(QPalette::Active, QPalette::HighlightedText)); mainEditor.setPalette(p); mainEditor.setParent(this); mainEditor.setAcceptDrops(false); setCentralWidget(&mainEditor); return ret; }
void write(QString f) { QFile file(f); if( file.open(QIODevice::WriteOnly | QIODevice::Text) ) { file.write("D.T.Software\n"); file.write("Delphi Tang\n"); file.close(); } } void read(QString f) { QFile file(f); if( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { QByteArray ba = file.readLine(); QString s(ba); qDebug() << s; file.close(); } } void info(QString f) { QFile file(f); QFileInfo info(file); qDebug() << info.exists(); qDebug() << info.isFile(); qDebug() << info.isReadable(); qDebug() << info.isWritable(); qDebug() << info.created(); qDebug() << info.lastRead(); qDebug() << info.lastModified(); qDebug() << info.path(); qDebug() << info.fileName(); qDebug() << info.suffix(); qDebug() << info.size(); }
Qt 中將文件類型分爲 2 大類github
Qt 提供輔助類簡化了文本文件/數據文件的讀寫算法
void text_stream_test(QString f) { QFile file(f); if( file.open(QIODevice::WriteOnly | QIODevice::Text) ) { QTextStream out(&file); out << QString("D.T.Software") << endl; out << QString("Result: ") << endl; out << 5 << '*' << 6 << '=' << 5 * 6 << endl; file.close(); } if( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { QTextStream in(&file); while( !in.atEnd() ) { QString line = in.readLine(); qDebug() << line; } file.close(); } } void data_stream_test(QString f) { QFile file(f); if( file.open(QIODevice::WriteOnly) ) { QDataStream out(&file); out.setVersion(QDataStream::Qt_4_7); out << QString("D.T.Software"); out << QString("Result: "); out << 3.14; file.close(); } if( file.open(QIODevice::ReadOnly) ) { QDataStream in(&file); QString dt = ""; QString result = ""; double value = 0; in.setVersion(QDataStream::Qt_4_7); in >> dt; in >> result; in >> value; file.close(); qDebug() << dt; qDebug() << result; qDebug() << value; } }
不一樣 Qt 版本的數據流文件格式可能不一樣數據庫
void write_buffer(int type, QBuffer& buffer) { if( buffer.open(QIODevice::WriteOnly) ) { QDataStream out(&buffer); out << type; if( type == 0 ) { out << QString("D.T.Software"); out << QString("3.1415"); } else if( type == 1 ) { out << 3; out << 1415; } else if( type == 2 ) { out << 3.1415; } buffer.close(); } } void read_buffer(QBuffer& buffer) { if( buffer.open(QIODevice::ReadOnly) ) { int type = -1; QDataStream in(&buffer); in >> type; if( type == 0 ) { QString dt = ""; QString pi = ""; in >> dt; in >> pi; qDebug() << dt; qDebug() << pi; } else if( type == 1 ) { int a = 0; int b = 0; in >> a; in >> b; qDebug() << a; qDebug() << b; } else if( type == 2 ) { double pi = 0; in >> pi; qDebug() << pi; } buffer.close(); } } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QByteArray array; QBuffer buffer(&array); write_buffer(2, buffer); read_buffer(buffer); return a.exec(); }
int MainWindow::showQueryMessage(QString message) { QMessageBox msg(this); msg.setIcon(QMessageBox::Question); msg.setWindowTitle("記事本"); msg.setWindowFlag(Qt::Drawer); msg.setText(message); msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); return msg.exec(); } void MainWindow::preEditChange() { if( m_isTextChanged ) { QString path = (m_filePath != "") ? m_filePath : "無標題"; int r = showQueryMessage(QString("是否將更改保存到\n") + "\"" + path + "\" ?"); switch ( r ) { case QMessageBox::Yes: saveCurrentData("保存", m_filePath); break; case QMessageBox::No: m_isTextChanged = false; break; case QMessageBox::Cancel: break; } } } void MainWindow::openFileEditor(QString path) { if( path != "" ) { QFile file(path); if( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { QTextStream in(&file); in.setCodec("GBK"); mainEditor.setPlainText(in.readAll()); file.close(); m_filePath = path; m_isTextChanged = false; setWindowTitle(m_filePath + "- 記事本"); } else { showErrorMessage(QString("打開文件失敗!\n\n") + "\"" + path + "\"。"); } } } void MainWindow::openFile(QString path) { preEditChange(); if( !m_isTextChanged ) { openFileEditor(path); } } void MainWindow::onFileOpen() { preEditChange(); if( !m_isTextChanged ) { QString path = showFileDialog(QFileDialog::AcceptOpen, "打開", ":/Res/pic/logo.png"); openFileEditor(path); } } QString MainWindow::saveCurrentData(QString title, QString path) { QString ret = path; if( ret == "" ) { ret = showFileDialog(QFileDialog::AcceptSave, title, ":/Res/pic/logo.png"); } if( ret != "" ) { QFile file(ret); if( file.open(QIODevice::WriteOnly | QIODevice::Text) ) { QTextStream out(&file); out << mainEditor.toPlainText(); file.close(); setWindowTitle(ret + " - 記事本"); m_isTextChanged = false; } else { showErrorMessage(QString("保存文件失敗!\n\n") + "\"。" + ret + "\""); } } return ret; } void MainWindow::onFileSave() { QString path = saveCurrentData("保存", m_filePath); if( path != "" ) { m_filePath = path; } } void MainWindow::onFileSaveAs() { QString path = saveCurrentData("另存爲"); if( path != "" ) { m_filePath = path; } }
使用關鍵槽函數判斷數據狀態segmentfault
判斷是由存在未保存的數據緩存
void MainWindow::onTextChanged() { if( !m_isTextChanged ) { setWindowTitle("* " + windowTitle()); } m_isTextChanged = true; statusLabel.setText("length: " + QString::number(mainEditor.toPlainText().length()) + " lines: " + QString::number(mainEditor.document()->lineCount())); }
void MainWindow::onFileNew() { preEditChange(); if( !m_isTextChanged ) { mainEditor.clear(); m_isTextChanged = false; setWindowTitle("新建文本文檔 - 記事本"); } }
QString MainWindow::showFileDialog(QFileDialog::AcceptMode mode, QString title, QString icon) { QFileDialog fd(this); QStringList filters; QMap<QString, QString> map; const char* filterArray[][2] = { {"文本文檔(*.txt)", ".txt"}, {"全部文件(*.*)" , ".*" }, {nullptr , nullptr} }; QString ret = ""; for(int i=0; filterArray[i][0]!=nullptr; i++) { filters.append(filterArray[i][0]); map.insert(filterArray[i][0], filterArray[i][1]); } fd.setWindowTitle(title); fd.setWindowIcon(QIcon(icon)); fd.setAcceptMode(QFileDialog::AcceptOpen); fd.setNameFilters(filters); if( mode == QFileDialog::AcceptOpen ) { fd.setFileMode(QFileDialog::ExistingFile); } if( fd.exec() == QFileDialog::Accepted ) { ret = fd.selectedFiles()[0]; if( mode == QFileDialog::AcceptSave ) { QString postfix = map[fd.selectedNameFilter()]; if( (postfix != ".*") && !ret.endsWith(postfix) ) { ret = ret + postfix; } } } return ret; }
/** *@brief 重寫關閉事件處理函數 */ void MainWindow::closeEvent(QCloseEvent *event) { preEditChange(); if( !m_isTextChanged ) { QFont font = mainEditor.font(); bool isWrap = (mainEditor.lineWrapMode() == QPlainTextEdit::WidgetWidth); bool tbVisible = (findMenuBarAction("工具欄")->isCheckable() && findToolBarAction("工具欄")->isChecked()); bool sbVisible = (findMenuBarAction("狀態欄")->isCheckable() && findToolBarAction("狀態欄")->isChecked()); AppConfig config(mainEditor.font(), size(), pos(), isWrap, tbVisible, sbVisible, this); config.store(); QMainWindow::closeEvent(event); } else { event->ignore(); } } /** *@brief 查找菜單欄中對應的 ACtion */ QAction* MainWindow::findMenuBarAction(QString text) { QAction* ret = nullptr; const QObjectList& list = menuBar()->children(); for(int i=0; i<list.count(); i++) { QMenu* men = dynamic_cast<QMenu*>(list[i]); if( men != nullptr ) { QList<QAction*> actions = men->actions(); for(int j=0; j<actions.count(); j++) { if( actions[j]->text().startsWith(text) ) { ret = actions[j]; break; } } } } return ret; } /** *@brief 查找工具欄中對應的 ACtion */ QAction* MainWindow::findToolBarAction(QString text) { QAction* ret = nullptr; QList<QAction*> actions = toolBar()->actions(); for(int j=0; j<actions.count(); j++) { if( actions[j]->toolTip().startsWith(text) ) { ret = actions[j]; break; } } return ret; }
拖放事件的處理函數爲:安全
重寫 dragEnterEvent 函數並判斷 MIME 類型數據結構
重寫 dropEvent 函數並判斷 MIMI 類型架構
void MainWindow::dragEnterEvent(QDragEnterEvent* event) { if( event->mimeData()->hasUrls() ) { event->acceptProposedAction(); } else { event->ignore(); } } void MainWindow::dropEvent(QDropEvent* event) { if( event->mimeData()->hasUrls() ) { QList<QUrl> list = event->mimeData()->urls(); QString path = list[0].toLocalFile(); QFileInfo fi(path); if( fi.isFile() ) { preEditChange(); if( !m_isTextChanged ) { openFileEditor(path); } } else { showErrorMessage(QString("對 ") + "\"" + path + "\" 的訪問被拒絕。"); } } else { event->ignore(); } }
QTextDocument 是表示文本以及文本屬性的數據類
void MainWindow::onFilePrint() { QPrintDialog dlg(this); dlg.setWindowTitle("打印"); if( dlg.exec() == QPrintDialog::Accepted ) { QPrinter* p = dlg.printer(); p->setPageLayout(m_pPageSetupDlg->printer()->pageLayout()); mainEditor.document()->print(p); } }
思路
算法流程描述
void MainWindow::onCursorPositionChanged() { int col = 0; int ln = 0; int flg = -1; int pos = mainEditor.textCursor().position(); QString text = mainEditor.toPlainText(); for(int i=0; i<pos; i++) { if( text[i] == '\n' ) { ln ++; flg = i; } } flg ++; col = pos - flg; statusCursorLabel.setText("Ln: " + QString::number(ln + 1) + " Col: " + QString::number(col + 1)); }
QApplication 類提供了支持事件發送的靜態成員函數
注意事項
sendEvent 中事件對象的生命期由 Qt 平臺管理
postEvent 中事件對象的生命期由 Qt 平臺管理
void MainWindow::onEditDelete() { QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier); QKeyEvent keyRelease(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier); QApplication::sendEvent(&mainEditor, &keyPress); QApplication::sendEvent(&mainEditor, &keyRelease); }
文件: FindDialog.h
#ifndef FINDDIALOG_H #define FINDDIALOG_H #include <QDialog> #include <QGridLayout> #include <QHBoxLayout> #include <QGroupBox> #include <QLabel> #include <QLineEdit> #include <QPushButton> #include <QCheckBox> #include <QRadioButton> #include <QPointer> #include <QPlainTextEdit> class FindDialog : public QDialog { Q_OBJECT protected: QGroupBox m_radioGrpBx; QGridLayout m_layout; QHBoxLayout m_hbLayout; QLabel m_findLbl; QLineEdit m_findEdit; QPushButton m_findBtn; QPushButton m_cancelBtn; QCheckBox m_matchChkBx; QRadioButton m_upwardBtn; QRadioButton m_downwardBtn; QPointer<QPlainTextEdit> m_pText; // 注意這裏,弱耦合設計!! void initControl(); void connectSlot(); public slots: void onFindClicked(); void onCancelClicked(); public: FindDialog(QWidget* parent = nullptr, QPlainTextEdit* pText = nullptr); void setPlainTextEdit(QPlainTextEdit* pText); QPlainTextEdit* getPlainTextEdit(); bool event(QEvent* e); ~FindDialog(); }; #endif // FINDDIALOG_H
文件:FindDialog.cpp
#include "FindDialog.h" #include <QEvent> #include <QTextCursor> #include <QMessageBox> FindDialog::FindDialog(QWidget* parent, QPlainTextEdit* pText) : QDialog (parent, Qt::WindowCloseButtonHint | Qt::Drawer) { initControl(); connectSlot(); setLayout(&m_layout); setFixedSize(450, 120); setWindowTitle("查找"); setPlainTextEdit(pText); } void FindDialog::initControl() { m_findLbl.setText("查找目標:"); m_findBtn.setText("查找下一個(&F)"); m_cancelBtn.setText("取消"); m_matchChkBx.setText("區分大小寫(&C)"); m_radioGrpBx.setTitle("方向"); m_upwardBtn.setText("向上(&U)"); m_downwardBtn.setText("向下(&D)"); m_downwardBtn.setChecked(true); m_hbLayout.addWidget(&m_upwardBtn); m_hbLayout.addWidget(&m_downwardBtn); m_radioGrpBx.setLayout(&m_hbLayout); m_layout.addWidget(&m_findLbl, 0, 0); m_layout.addWidget(&m_findEdit, 0, 1); m_layout.addWidget(&m_findBtn, 0, 2); m_layout.addWidget(&m_matchChkBx, 1, 0); m_layout.addWidget(&m_radioGrpBx, 1, 1); m_layout.addWidget(&m_cancelBtn, 1, 2); } void FindDialog::connectSlot() { connect(&m_findBtn, SIGNAL(clicked()), this, SLOT(onFindClicked())); connect(&m_cancelBtn, SIGNAL(clicked()), this, SLOT(onCancelClicked())); } void FindDialog::setPlainTextEdit(QPlainTextEdit* pText) { m_pText = pText; } QPlainTextEdit* FindDialog::getPlainTextEdit() { return m_pText; } void FindDialog::onFindClicked() { QString target = m_findEdit.text(); if( (m_pText != nullptr) && (target != "") ) { QString text = m_pText->toPlainText(); QTextCursor c = m_pText->textCursor(); int index = -1; if( m_downwardBtn.isChecked() ) { index = text.indexOf(target, c.position(), m_matchChkBx.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive); if( index >= 0 ) { c.setPosition(index); c.setPosition(index + target.length(), QTextCursor::KeepAnchor); m_pText->setTextCursor(c); } } if( m_upwardBtn.isChecked() ) { index = text.lastIndexOf(target, c.position() - text.length() - 1, m_matchChkBx.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive); if( index >=0 ) { c.setPosition(index + target.length()); c.setPosition(index, QTextCursor::KeepAnchor); m_pText->setTextCursor(c); } } if( index < 0 ) { QMessageBox msg(this); msg.setWindowTitle("記事本"); msg.setText(QString("找不到 ") + "\"" + target + "\""); msg.setWindowFlag(Qt::Drawer); msg.setIcon(QMessageBox::Information); msg.setStandardButtons(QMessageBox::Ok); msg.exec(); } } } void FindDialog::onCancelClicked() { close(); } bool FindDialog::event(QEvent* e) { if( e->type() == QEvent::Close ) { hide(); // 爲了保持上一次用戶的操做屬性,進隱藏窗口 return true; } return QDialog::event(e); } FindDialog::~FindDialog() { }
文件:ReplaceDialog.h
#ifndef REPLACEDIALOG_H #define REPLACEDIALOG_H #include "FindDialog.h" class ReplaceDialog : public FindDialog { Q_OBJECT protected: QLabel m_replaceLbl; QLineEdit m_replaceEdit; QPushButton m_replaceBtn; QPushButton m_replaceAllBtn; void initControl(); void connectSlot(); protected slots: void onReplaceClicked(); void onReplaceAllClicked(); public: ReplaceDialog(QWidget* parent = nullptr, QPlainTextEdit* pText = nullptr); }; #endif // REPLACEDIALOG_H
文件:ReplaceDialog.cpp
#include "ReplaceDialog.h" ReplaceDialog::ReplaceDialog(QWidget* parent, QPlainTextEdit* pText) : FindDialog (parent, pText) { initControl(); connectSlot(); } void ReplaceDialog::initControl() { m_replaceLbl.setText("替換爲:"); m_replaceBtn.setText("替換(&R)"); m_replaceAllBtn.setText("所有替換(&A)"); m_layout.removeWidget(&m_matchChkBx); m_layout.removeWidget(&m_radioGrpBx); m_layout.removeWidget(&m_cancelBtn); m_layout.addWidget(&m_replaceLbl, 1, 0); m_layout.addWidget(&m_replaceEdit, 1, 1); m_layout.addWidget(&m_replaceBtn, 1, 2); m_layout.addWidget(&m_matchChkBx, 2, 0); m_layout.addWidget(&m_radioGrpBx, 2, 1); m_layout.addWidget(&m_replaceAllBtn, 2, 2); m_layout.addWidget(&m_cancelBtn, 3, 2); setFixedSize(450, 170); setWindowTitle("替換"); } void ReplaceDialog::connectSlot() { connect(&m_replaceBtn, SIGNAL(clicked()), this, SLOT(onReplaceClicked())); connect(&m_replaceAllBtn, SIGNAL(clicked()), this, SLOT(onReplaceAllClicked())); } void ReplaceDialog::onReplaceClicked() { QString target = m_findEdit.text(); QString to = m_replaceEdit.text(); if( (m_pText != nullptr) && (target != "") && (to != "") ) { QString selText = m_pText->textCursor().selectedText(); if( selText == target ) { m_pText->insertPlainText(to); } onFindClicked(); } } void ReplaceDialog::onReplaceAllClicked() { QString target = m_findEdit.text(); QString to = m_replaceEdit.text(); if( (m_pText != nullptr) && (target != "") && (to != "") ) { QString text = m_pText->toPlainText(); text.replace(target, to, m_matchChkBx.isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive); m_pText->clear(); m_pText->insertPlainText(text); } }
QPalette 對象包含了三個狀態的顏色描述
激活顏色組(Active)
非激活顏色組(Inactive)
失效顏色組(Disabled)
調色板是存儲組件顏色信息的數據結構
組件外觀所使用的顏色都位於調色板中
QPalette p = mainEditor.palette(); p.setColor(QPalette::Inactive, QPalette::Highlight, p.color(QPalette::Active, QPalette::Highlight)); p.setColor(QPalette::Inactive, QPalette::HighlightedText, p.color(QPalette::Active, QPalette::HighlightedText)); mainEditor.setPalette(p);
算法設計
void MainWindow::onEditGoto() { bool ok = false; int ln = QInputDialog::getInt(this, "轉到", "行號:", 1, 1, mainEditor.document()->lineCount(), 1, &ok, Qt::WindowCloseButtonHint | Qt::Drawer); if( ok ) { QString text = mainEditor.toPlainText(); QTextCursor c = mainEditor.textCursor(); int pos = 0; int next = -1; for(int i=0; i<ln; i++) { pos = next + 1; next = text.indexOf('\n', pos); } c.setPosition(pos); mainEditor.setTextCursor(c); } }
實現思路
更新界面上 QAction 對象的狀態
void MainWindow::onViewToolBar() { QToolBar* tb = toolBar(); bool visible = tb->isVisible(); tb->setVisible(!visible); findMenuBarAction("工具欄")->setChecked(!visible); findToolBarAction("工具欄")->setChecked(!visible); } void MainWindow::onViewStatusBar() { QStatusBar* sb = statusBar(); bool visible = sb->isVisible(); sb->setVisible(!visible); findMenuBarAction("狀態欄")->setChecked(!visible); findToolBarAction("狀態欄")->setChecked(!visible); }
實現思路
void MainWindow::FormatFont() { bool ok = false; QFont font = QFontDialog::getFont(&ok, mainEditor.font(), this, "打印"); if( ok ) { mainEditor.setFont(font); } }
void MainWindow::FormatWrap() { QPlainTextEdit::LineWrapMode mode = mainEditor.lineWrapMode(); if( mode == QPlainTextEdit::NoWrap ) { mainEditor.setLineWrapMode(QPlainTextEdit::WidgetWidth); findMenuBarAction("自動換行")->setChecked(true); findToolBarAction("自動換行")->setChecked(true); } else { mainEditor.setLineWrapMode(QPlainTextEdit::NoWrap); findMenuBarAction("自動換行")->setChecked(false); findToolBarAction("自動換行")->setChecked(false); } }
void MainWindow::onHelpManual() { QDesktopServices::openUrl(QUrl("https://segmentfault.com/u/tiansong")); }
狀態參數的存儲方式
Qt 中的解決方案
優點:
文件: AppConfig.h
#ifndef APPCONFIG_H #define APPCONFIG_H #include <QObject> #include <QFont> #include <QPoint> #include <QSize> class AppConfig : public QObject { protected: QFont m_editFont; QSize m_mainWindowSize; QPoint m_mainWindowPoint; bool m_isAutoWrap; bool m_isToolBarVisible; bool m_isStatusVisible; bool m_isVilid; bool restore(); public: explicit AppConfig(QObject *parent = nullptr); explicit AppConfig(QFont font, QSize size, QPoint point, bool isWrap, bool tbvisible, bool sbVisible, QObject *parent = nullptr); bool store(); QFont editFont(); QSize mainWindowSize(); QPoint mainWindowPoint(); bool isAutoWrap(); bool isToolBarVisible(); bool isStatusVisible(); bool isVilid(); }; #endif // APPCONFIG_H
文件: AppConfig.cpp
#include "AppConfig.h" #include <QFile> #include <QDataStream> #include <QApplication> AppConfig::AppConfig(QObject *parent) : QObject(parent) { m_isVilid = restore(); } AppConfig::AppConfig(QFont font, QSize size, QPoint point, bool isWrap, bool tbvisible, bool sbVisible, QObject *parent) : QObject(parent) { m_editFont = font; m_mainWindowSize = size; m_mainWindowPoint = point; m_isAutoWrap = isWrap; m_isToolBarVisible = tbvisible; m_isStatusVisible = sbVisible; m_isVilid = true; } bool AppConfig::restore() { bool ret = true; QFile file(QApplication::applicationDirPath() + "/app.config"); if( file.open(QIODevice::ReadOnly) ) { QDataStream in(&file); in >> m_editFont; in >> m_mainWindowSize; in >> m_mainWindowPoint; in >> m_isAutoWrap; in >> m_isToolBarVisible; in >> m_isStatusVisible; file.close(); } else { ret = false; } return ret; } bool AppConfig::store() { bool ret = true; QFile file(QApplication::applicationDirPath() + "/app.config"); if( file.open(QIODevice::WriteOnly) ) { QDataStream out(&file); out << m_editFont; out << m_mainWindowSize; out << m_mainWindowPoint; out << m_isAutoWrap; out << m_isToolBarVisible; out << m_isStatusVisible; file.close(); } else { ret = false; } return ret; } QFont AppConfig::editFont() { return m_editFont; } QSize AppConfig::mainWindowSize() { return m_mainWindowSize; } QPoint AppConfig::mainWindowPoint() { return m_mainWindowPoint; } bool AppConfig::isAutoWrap() { return m_isAutoWrap; } bool AppConfig::isToolBarVisible() { return m_isToolBarVisible; } bool AppConfig::isStatusVisible() { return m_isStatusVisible; } bool AppConfig::isVilid() { return m_isVilid; }
應用程序退出的過程
Qt 中的解決方案
void MainWindow::closeEvent(QCloseEvent *event) { preEditChange(); if( !m_isTextChanged ) { QFont font = mainEditor.font(); bool isWrap = (mainEditor.lineWrapMode() == QPlainTextEdit::WidgetWidth); bool tbVisible = (findMenuBarAction("工具欄")->isCheckable() && findToolBarAction("工具欄")->isChecked()); bool sbVisible = (findMenuBarAction("狀態欄")->isCheckable() && findToolBarAction("狀態欄")->isChecked()); AppConfig config(mainEditor.font(), size(), pos(), isWrap, tbVisible, sbVisible, this); config.store(); QMainWindow::closeEvent(event); } else { event->ignore(); } }
命令行參數的應用 一
傳統應用方式
命令行參數的應用 二
操做系統關聯方式
int main(int argc, char *argv[]) { QApplication a(argc, argv); int ret = -1; if( w != nullptr ) { if( argc > 1 ) { QFileInfo fi(argv[1]); if( fi.exists() ) { w->openFile(argv[1]); } } w->show(); ret = a.exec(); delete w; } return ret; }
調試版(debug): 開發階段的可執行程序
發佈版(release): 最終產品的可執行程序
Linux 中可使用 ldd 命令查看程序的依賴庫
可能的依賴:
Window 下的環境部署
Linux 下的環境部署
方式一:
方式二:
以上內容參考狄泰軟件學院系列課程,請你們保護原創!