1. 程式人生 > >Qt 介面設計總結

Qt 介面設計總結

把工作中學到的技巧記錄下來:

1. 子窗體或控制元件,重寫paintEvent事件,畫邊框、背景、文字、圖片效果比較好。用paintEvent 事件畫邊框,用QPalette設定背景。

// 畫邊框

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(QPen(QColor(225,70,56), 2));
//    painter.setBrush(QColor(16,62,81));   // 也可設定背景,有時效果不好

    painter.drawRoundedRect(rect(), 5.0, 5.0);

// 設定背景

    QPalette pal = palette();
    pal.setBrush(QPalette::Window, QColor(16,62,81));
    setPalette(pal);
    setAutoFillBackground(true);

2. 繼承QDialog,想讓對話方塊以模態執行,使用exec(),繼承時使用setWindowFlags()後則達不到模態的效果。不知道原因。

3. QStringList 輸出

QStringList m_strLang << "English"

                                          << "Chinese";

qDebug("set language: %s", m_strLang.at(0).toLocal8Bit().constData());

4. QStringList 使用注意

    QStringList strDateformatList;
    strDateformatList
            << m_strMonth + "-" + m_strDay + "-" + m_strYear
            << m_strDay + "-" + m_strMonth + "-" + m_strYear
            << m_strYear + "-" + m_strMonth + "-" + m_strDay
            ;

如果strDateformatList 在生命週期內多次呼叫,則會多次插入字串,使得字串重複,這不是我們想要的。那就定義為區域性變數,每次會重新賦值,達到更新的目的。

5.需要動態重新的頁面可以在showEvent函式中重新。

6. 用paintEvent或用調色盤為QWidget填充背景時,需要加上setAutoFillBackground(true);語句,否則沒效果。

7. 想使彈出的視窗為圓角,用paintEvent畫圓角矩形,但四個直角仍然存在,不美觀。可以把背景設為透明,用paintEvent畫出想要的背景,因為四個角沒有畫上背景,是透明的,所以看不見。

     // 設定背景為透明 (建構函式中)

    QPalette pal = palette();
    pal.setBrush(QPalette::Window, QColor(255, 255, 255, 0));
    setPalette(pal);
    setAutoFillBackground(true);

    // 畫背景和邊框 (paintEvent函式中)

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(QPen(QColor(225,70,56), 2));
    painter.setBrush(QColor(16,62,81));

    painter.drawRoundedRect(rect(), 5.0, 5.0);

 8. Qt::Key_Enter、Qt::Key_Reture

Qt::Key_Enter對應小鍵盤的Enter鍵

Qt::Key_Return對應大鍵盤的Enter鍵

9. 事件過濾。視窗部件的事件到達目的地之前提前獲取並處理相關事件,實現個性化的處理。

我在QLabel物件中放入兩個QPushButton物件和兩個QLabel物件,QPushButton實現值的調節,其中一個QLabel物件用於顯示值,一個QLabel物件用於顯示標題。類似SpinBox。在多個SpinBox上點選實現焦點切換,當滑鼠點到QPushButton上時,QPushButton處理了mousePressEvent事件,所以無法實現焦點切換。為兩個QPushButton物件安裝事件過濾器,然後在其父部件中處理eventFilter函式

m_btnLeft->installEventFilter(this);

m_btnRight->installEventFilter(this);

//安裝事件過濾器後,傳給m_btnLeft、m_btnRight的事件會首先發送給eventFilter函式

boolESpinBoxItem::eventFilter(QObject*obj,QEvent*ev)

{
if(obj==m_btnLeft||obj==m_btnRight)
{
if(ev->type()==QEvent::MouseButtonPress)
{
emitsign_spinBoxPressed(m_nItem);
returntrue; // 不傳給目標物件處理
}
}
returnfalse; // 不處理的事件則傳給目標物件處理
}

10. 拍照動畫

使用QTimeLine和QGraphicsPixmapItem物件,當時間線幀改變時,設定QGraphicsPixmapItem的位置,實現動畫效果。

// 在QGraphicsView建構函式中

// take photo animation
    m_timerAnimation = new QTimeLine(900);
    m_timerAnimation->setCurveShape(QTimeLine::LinearCurve);
    m_timerAnimation->setFrameRange(0, 240);

    m_pixmapUpAnimation = QPixmap(":/images/animation.png");
    m_pixmapDownAnimation = QPixmap(":/images/animation.png");

    m_upPixmapItem = new QGraphicsPixmapItem;
    m_downPixmapItem = new QGraphicsPixmapItem;
    m_upPixmapItem->setZValue(4);
    m_downPixmapItem->setZValue(4);

    m_upPixmapItem->setPos(0, 0);            // 左上角為原點
    m_downPixmapItem->setPos(0, 240);

    scene()->addItem(m_upPixmapItem);
    scene()->addItem(m_downPixmapItem);

    m_upPixmapItem->hide();
    m_downPixmapItem->hide();

    connect(m_timerAnimation, SIGNAL(frameChanged(int)), this, SLOT(slot_playAnimation(int)));

// 槽函式

void EGraphicsView::slot_playAnimation(int nFrame)
{
    m_upPixmapItem->show();
    m_downPixmapItem->show();

    qDebug("nFrame: %d", nFrame);

    if(nFrame < 120)
    {
        m_upPixmapItem->setPixmap(m_pixmapUpAnimation.scaled(320, nFrame));
        m_downPixmapItem->setPixmap(m_pixmapDownAnimation.scaled(320, nFrame));
        m_downPixmapItem->setPos(0, 240 - nFrame);
    }
    else
    {
        m_upPixmapItem->setPixmap(m_pixmapUpAnimation.scaled(320, 240 - nFrame));
        m_downPixmapItem->setPixmap(m_pixmapDownAnimation.scaled(320, 240 - nFrame));
        m_downPixmapItem->setPos(0, nFrame);
    }
}

 11.在移動裝置上使用漸變或使用漸變的圖片時,會出現條紋狀,達不到效果。在初始化QApplication對像前呼叫下面的語句則可以達到效果:

QApplication::setColorSpec(QApplication::ManyColor); //the right choice for applications that use thousands of colors

QApplication app(argc, argv,  QApplication::GuiServer );

12.用setStyleSheet設定背景圖片

m_labelButton->setStyleSheet("background-image: url(:images/shutdown/slider.png); background-repeat: no-repeat;"); //注意,不加background-repeat: no-repeat可能會出現透視,很醜。QLabel物件可用setPixmap設定象素圖。

13.使對話方塊圓角

    //建構函式中

    setAutoFillBackground(true);

    QPalette pal = palette();

    pal.setColor(QPalette::Window, QColor(0, 0, 0, 0));

    setPalette(pal);

    //paintEvent函式中

   QPainter painter(this);

   painter.setRenderHint(QPainter::Antialiasing,true);

   painter.setPen(QPen(Qt::red,2));

   painter.setBrush(QColor(16,62,81));

   painter.drawRoundedRect(rect(),5.0,5.0);

 // 圓角處有雜色,原因不祥

 14. 對某些預設事件的處理修改

正常情況下,按下Tab鍵,被QWidget看成是去移動鍵盤焦點,但少數視窗部件需要自行解釋。

bool MyClass::event(QEvent *e)

{

         if(e->type() == QEvent::KeyPress)

         {

                 QKeyEvent *ke = (QKeyEvent *)e;

                 if(ke->key() == Qt::Key_Tab)

                  {

                            //這裡是特定的Tab處理

                            k->accept();

                            return TRUE;

                  }

         }

         else if(e->type()  >= QEvent::User)

         {

                 // 這裡是自定義事件處理

                 return TRUE;

          }

          QWidget::event(e);

}

   15.QLabel繼承QFrame,有QFrame的特性。如setFrameStyle(int)可設定QLabel的FrameStyle(框架型別)

FrameStyle有兩種:

a.第一種是frameshape:

有以下幾種型別:

Constant Value Description
QFrame::NoFrame 0 QFramedraws nothing
QFrame::Box 0x0001 QFramedraws a box around its contents
QFrame::Panel 0x0002 QFramedraws a panel to make the contents appear raised or sunken
QFrame::StyledPanel 0x0006 draws a rectangular panel with a look that depends on the current GUI style. It can be raised or sunken.
QFrame::HLine 0x0004 QFramedraws a horizontal line that frames nothing (useful as separator)
QFrame::VLine 0x0005 QFramedraws a vertical line that frames nothing (useful as separator)
QFrame::WinPanel 0x0003 draws a rectangular panel that can be raised or sunken like those in Windows 95. Specifying this shape sets the line width to 2 pixels. WinPanel is provided for compatibility. For GUI style independence we recommend using StyledPanel instead.

b.第二種是frameshadow

有以下幾種型別:

Constant Value Description
QFrame::Plain 0x0010 the frame and contents appear level with the surroundings; draws using the paletteQPalette::WindowTextcolor (without any 3D effect)
QFrame::Raised 0x0020 the frame and contents appear raised; draws a 3D raised line using the light and dark colors of the current color group
QFrame::Sunken 0x0030 the frame and contents appear sunken; draws a 3D sunken line using the light and dark colors of the current color group

 組合值的效果圖:

15.幾種位置資訊

x()、y()、pos()函式都是獲得整個窗體左上角的座標位置。需frameGeometry與geometry相對應,frameGemometry()是獲得整個窗體的左上頂點和長、寬值,需geometry()函式獲得的是窗體內中央域的左上頂點座標以及長、寬值。直接呼叫width()和height()函式獲得的是中央區域的長和寬的值。還有兩個函式rect()、size(),呼叫它們獲得的結果也都是對於窗體的中央區域而言的。size()獲得的是窗體中央區域的長、寬值,rect()與geometry()一樣返回一個QRect物件。其中,兩個函式獲得的長寬、值是一樣的,都是窗體中央區域的長、寬值,只是左上頂點的座標值不一樣,geometry()獲得的左上角頂點座標是相對於父窗體而言的座標,,而rect()獲得的左上角頂點座標始終為(0, 0)。

效果圖:

窗體在左上角時:

16.幾種輸入對話方塊。

a.獲取文字對話方塊

 QString strName=QInputDialog::getText(this,tr("User Name"),tr("Please Input New Name:"),QLineEdit::Normal,m_labelName->text(),&ok);

b.獲取項對話方塊

QStringList list;

list<<tr("男")<<tr("女");

QStringstrSex=QInputDialog::getItem(this,tr("User Sex"),tr("Please Select Sex:"),list,0,false,&ok);

c.獲取整數對話方塊

boolok;

    int nAge = QInputDialog::getInteger(this, tr("User Age"), tr("Please Input Age:"), m_labelAge->text().toInt(), 18, 30, 1, &ok);
    if(ok)
    {
        m_labelAge->setText(QString(tr("%1").arg(nAge)));
    }

d.獲得雙精度對話方塊

boolok;

doublenHeight=QInputDialog::getDouble(this,tr("User Height"),tr("Please Input Height:"),m_labelHeight->text().toDouble(),160.5,270.5,1,&ok);
if(ok)
{
m_labelHeight->setText(QString(tr("%1").arg(nHeight)));
}

 17.自定義QMessageBox

    QMessageBox customMsgBox;
customMsgBox.setWindowTitle("Custom message box");
QPushButton*lockButton=customMsgBox.addButton(tr("Lock"),QMessageBox::ActionRole);
QPushButton*unlockButton=customMsgBox.addButton(tr("Unlock"),QMessageBox::ActionRole);
QPushButton*cancelButton=customMsgBox.addButton(QMessageBox::Cancel);
customMsgBox.setIconPixmap(QPixmap(":/images/1.png"));
customMsgBox.setText(tr("This is a custom message box"));
customMsgBox.exec();
if(customMsgBox.clickedButton()==lockButton)
{
m_labelMessage->setText("Custom MessageBox button / lock");
}
elseif(customMsgBox.clickedButton()==unlockButton)
{
m_labelMessage->setText("Custom MessageBox button / unlock");
}
elseif(customMsgBox.clickedButton()==cancelButton)
{
m_labelMessage->setText("Custom MessageBox button / Cancel");
}

效果圖:

定義好的MessageBox

QMessageBox::question

QMessageBox::information

QMessageBox::warning

QMessageBox::critical

QMessageBox::about

QMessageBox::aboutQt

 18.在編寫程式時,初始化窗體時最好不要使用setGeometry()函式,而用resize()和move()函式代替,因為使用setGeometry()會導致窗體show()之後在錯誤 的位置上停留很短暫的一段時間,帶來閃爍現象。

19.提示錯誤:E:\vm_shared\study\graphicsview\debug\moc_navibar.cpp:39: error: `staticMetaObject' is not a member of `QGraphicsRectItem'

錯誤原因:因為QGraphicsRectItem不是QObject的子類,所以在類的宣告中不能有Q_OBJECT巨集、signal和slot。

20.抓圖功能:

// 使用Qt自帶的靜態函式grabWindow,指定窗體ID,抓圖的起啟位置和麵積大小。

QImage image = QPixmap::grabWindow(QApplication::desktop()->winId(), 0, 0, nDesktopWidth, nDesktopHeight).toImage().scaled(640, 480); 

21.檢視去掉滾動條

 view->setFrameShape(QFrame::NoFrame);

通過佈局指定檢視的父窗體時,使用上面程式碼去不掉滾動條。而需要使用view = new QGraphicsView(this);指定父窗體。

最好辦法是: view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 一直關掉滾動條

22.QpushButton圓角

QPushButton {
     border: 2px solid #8f8f91;
     border-radius: 6px;
     background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                       stop: 0 #f6f7fa, stop: 1 #dadbde);
     min-width: 80px;
 }

note: 當QPushButton無邊框(border: 0px;),有設定背景顏色(background-color: rgb(6,43,58);)時,設定圓角會出現鋸齒,因為圓角是邊框為圓角,邊框大小不能為0px.想讓按鈕只顯示一種顏色(看不見邊框顏色),則把邊框顏色設為背景色即可。如圖: