因為需要一個能夠接受事件的標籤元件,所以我定義了一個繼承自 QLabel 的物件:
class QEventLabel : public QLabel
{
public:
explicit QEventLabel(QWidget *parent = 0, Qt::WindowFlags f = 0);
explicit QEventLabel(const QString &text, QWidget *parent = 0,
Qt::WindowFlags f = 0);
~QEventLabel();
protected:
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
};
QEventLabel::QEventLabel(QWidget *parent, Qt::WindowFlags f) : QLabel(parent, f)
{
}
QEventLabel::QEventLabel(const QString &text, QWidget *parent,
Qt::WindowFlags f) : QLabel(text, parent, f)
{
}
QEventLabel::~QEventLabel()
{
}
建構子與解構子基本上都不需要做更動。
void QEventLabel::mouseMoveEvent(QMouseEvent *event)
{
QString msg;
msg.sprintf("<center>%d, %d</center>", event->x(), event->y());
this->setText(msg);
}
void QEventLabel::mousePressEvent(QMouseEvent *event)
{
QString msg;
msg.sprintf("<center>Press</center>");
this->setText(msg);
}
void QEventLabel::mouseReleaseEvent(QMouseEvent *event)
{
QString msg;
msg.sprintf("<center>Release</center>");
this->setText(msg);
}
在這裡的滑鼠是利用 QString 物件搭配 QString::sprintf() 函式來建立字串,以顯示標籤接收到的事件。
當滑鼠移動,標籤會顯示滑鼠的座標;當滑鼠按鍵被按下,標籤會顯示"Press";當滑鼠按鍵被釋放,標籤會顯示"Release"。
其中,滑鼠的座標可以由 QMouseEvent::x() 與 QMouseEvent::y() 取得。
void QEventLabel::keyPressEvent(QKeyEvent *event)
{
QString msg;
if (event->key() == '<')
{
msg = "<center>Type: <</center>";
}
else if (event->key() >= Qt::Key_Space && event->key() <= Qt::Key_AsciiTilde)
{
msg = "<center>Type: " + event->text() + "</center>";
}
else
{
msg.sprintf("<center>Type: <font color=red>%d</font></center>", event->key());
}
this->setText(msg);
}
這裡的鍵盤處理器也與滑鼠處理器相同,利用了 QString 物件與 QString::sprintf() 函式來顯示接收到的事件。
當鍵盤被按下時,若是可以直接印出的字元('D'、' '、'!'、'3'等符號),我利用了 QKeyEvent::text() 取得鍵盤代號所對應的符號,並將之顯示在標籤上;而若是不能印出的功能鍵(Enter、Shift、Home 等),我則利用 QKeyEvent::key() 直接在標籤上顯示鍵盤代號。
要特別注意的是,若鍵盤代號對應的是上角括號'<',直接利用 QKeyEvent::text() 會被判定為 html 標籤而不顯示。為了避免這種情況,我就將之改成直接輸出"<",也就是'<'的字元實體(character entity)。
然後,別忘了在之前建立 QLabel 實體的地方做一點更動:
QEventLabel *label = new QEventLabel("<center>No Event</center>", window);
簡單來說,就是把 QLabel 改成 QEventLabel,並將標籤文字改成"No Event"就可以了。
這樣應該完成了吧?試著先編譯執行看看。
當滑鼠在標籤上移動,標籤成功的顯示滑鼠所在的座標。試著按看看滑鼠左右鍵,這個功能也正常運作了,看來一切完美。最後再按一按鍵盤......。等一等,為什麼按下鍵盤卻沒有反應呢?
這個問題讓我修改又測試了一陣子,我猜想大概是標籤並沒有取得鍵盤的焦點(focus)。有了如此推測之後,又翻了一下官方的函式庫,發現這個 QWidget::setFocus() 函式似乎是我所需要的解答。
label->setFocus();
將這段程式碼加進去之後,編譯執行試看看。Bingo!現在標籤也能成功取得鍵盤事件囉。
完整的程式碼如下:
#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QDesktopWidget>
#include <QMouseEvent>
#include <QKeyEvent>
#define WIDTH 290
#define HEIGHT 140
/**************************************
創建一個能接收事件的 Label 類別
**************************************/
class QEventLabel : public QLabel
{
public:
explicit QEventLabel(QWidget *parent = 0, Qt::WindowFlags f = 0);
explicit QEventLabel(const QString &text, QWidget *parent = 0,
Qt::WindowFlags f = 0);
~QEventLabel();
protected:
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
};
/**************************************
QEventLabel 建構子
**************************************/
QEventLabel::QEventLabel(QWidget *parent, Qt::WindowFlags f) : QLabel(parent, f)
{
}
QEventLabel::QEventLabel(const QString &text, QWidget *parent,
Qt::WindowFlags f) : QLabel(text, parent, f)
{
}
QEventLabel::~QEventLabel()
{
}
/**************************************
QEventLabel 事件處理
**************************************/
void QEventLabel::mouseMoveEvent(QMouseEvent *event)
{
QString msg;
msg.sprintf("<center>%d, %d</center>", event->x(), event->y());
this->setText(msg);
}
void QEventLabel::mousePressEvent(QMouseEvent *event)
{
QString msg;
msg.sprintf("<center>Press</center>");
this->setText(msg);
}
void QEventLabel::mouseReleaseEvent(QMouseEvent *event)
{
QString msg;
msg.sprintf("<center>Release</center>");
this->setText(msg);
}
void QEventLabel::keyPressEvent(QKeyEvent *event)
{
QString msg;
if (event->key() == '<')
{
// 避免上角括號被當作標籤而不顯示
msg = "<center>Type: <</center>";
}
else if (event->key() >= Qt::Key_Space && event->key() <= Qt::Key_AsciiTilde)
{
msg = "<center>Type: " + event->text() + "</center>";
}
else
{
msg.sprintf("<center>Type: <font color=red>%d</font></center>", event->key());
}
this->setText(msg);
}
/**************************************
Main 主函式
**************************************/
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *window = new QWidget;
window->setWindowTitle("Hello, Qt!");
window->setMinimumSize(WIDTH, HEIGHT);
window->setMaximumSize(WIDTH, HEIGHT);
// 調整視窗至螢幕中央
QSize size = app.desktop()->size();
window->move((size.width() - WIDTH) / 2, (size.height() - HEIGHT) / 2);
// 建立並設定元件
QEventLabel *label = new QEventLabel("<center>No Event</center>", window);
label->setFont(QFont("Courier New", 25, QFont::Bold));
label->setGeometry(0, 0, 290, 70);
QPushButton *quit = new QPushButton("&Quit", window);
quit->setFont(QFont("Monotype Corsiva", 25, QFont::Bold));
quit->setGeometry(5, 75, 280, 60);
QObject::connect(quit, SIGNAL(clicked()), &app, SLOT(quit()));
// 使 Label 變為焦點
label->setFocus();
window->show();
return app.exec();
}
編譯執行之後的結果:
編譯出來的程式,我試著轉移到沒有裝 Qt 的電腦執行。沒想到還需要附帶 Qt 目錄下 lib 資料夾的 QtCore4.dll、QtGui4.dll 等動態函式庫。而這些動態函式庫的檔案也都不小,光一個 QtGui4.dll 就要將近 10 MB。
不過怎麼說,還算是滿好學、好用的,有時間再寫些別的吧!或許來試用一下 Qt Designer。
0 回覆:
張貼留言