C++ Qt QColorDialog-退出键不为“;“吃”;(即不从事件队列中删除)
在我的应用程序中,我有一个QTableWidget,其中有一列用户可以单击以选择颜色。它在以下限制下正常工作:当用户键入转义键时,对话框将按预期取消并关闭,但键事件仍保留在队列中。当对话框关闭时,这将导致此键事件的第二个效果,就像用户按了两次键一样 以下是全部代码:C++ Qt QColorDialog-退出键不为“;“吃”;(即不从事件队列中删除),c++,qt,events,dialog,C++,Qt,Events,Dialog,在我的应用程序中,我有一个QTableWidget,其中有一列用户可以单击以选择颜色。它在以下限制下正常工作:当用户键入转义键时,对话框将按预期取消并关闭,但键事件仍保留在队列中。当对话框关闭时,这将导致此键事件的第二个效果,就像用户按了两次键一样 以下是全部代码: void CChildrenConfigScreen::actionCellClicked(int row, int col) { // ui->config_children_table->selectRow
void CChildrenConfigScreen::actionCellClicked(int row, int col)
{
// ui->config_children_table->selectRow(row);
switch(col) {
case eColChildColor: {
CBiStateButton* cbox = reinterpret_cast<CBiStateButton*>(ui->config_children_table->cellWidget(row, 0));
assert( cbox != nullptr );
if( cbox->state() != Qt::Unchecked ) {
QTableWidgetItem* cell = ui->config_children_table->item(row, col);
cell->setSelected(false);
// =======
QColorDialog dialog(this);
dialog.setCurrentColor(cell->background().color());
dialog.exec();
if( dialog.result() == QDialog::Accepted ) {
cell->setBackground(QBrush(dialog.currentColor()));
} else {
// drop escape key event ???
}
// =======
}
}
break;
}
}
void CChildrenConfigScreen::actionCellClicked(int行,int列)
{
//用户界面->配置子表->选择行(行);
开关(col){
案例生态儿童颜色:{
CBiStateButton*cbox=重新解释强制转换(ui->config_children_table->cellWidget(行,0));
断言(cbox!=nullptr);
如果(cbox->state()!=Qt::未选中){
QTableWidgetItem*cell=ui->config\u children\u table->item(行、列);
单元格->所选设置(假);
// =======
QColorDialog对话框(此对话框);
setCurrentColor(单元格->背景().color());
dialog.exec();
if(dialog.result()==QDialog::Accepted){
单元格->设置背景(QBrush(dialog.currentColor());
}否则{
//丢钥匙事件???
}
// =======
}
}
打破
}
}
所以,我的问题是:
- 如果是,什么
- 如果没有,我可以做什么来“吃”这个活动?(最好不用创建QColorDialog子类)
- 以下是我实施的解决方案。不是很漂亮,但我能做到最好,并按要求工作。定义有点冗长,但使用起来非常方便
首先,一个基于堆栈的对象(Android和MacOS尚未实现,只有Windows):
跳过实际上已经处理过的Esc键(在本例中,在上面的QColorDialog中,但可能是QMessageBox或任何其他对话框):
我希望这对某些人有用。使用了一种难看的解决方法,在“else”代码块中设置标志,以避免在其他地方处理事件。很难看,但一切都在控制之中,运作良好,但我想知道发生了什么。非常奇怪。将尝试QCoreApplication::installNativeEventFilter和QCoreApplication::removeNativeEventFilter
// ==============================
// Used to disable the Escape key
class CKeyEventFilter {
public:
typedef char KeyType;
typedef std::function<void()> Functor;
private:
class CFilter: public QAbstractNativeEventFilter
{
public:
private:
KeyType mKey;
Functor mAction;
public:
explicit CFilter(KeyType key, Functor action)
: mKey(key)
, mAction(action)
{
}
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override
{
bool stop_it = false;
#if defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)
if (eventType == "xcb_generic_event_t") {
xcb_generic_event_t* event = reinterpret_cast<xcb_generic_event_t *>(message);
assert(event != nullptr);
// ...
}
#elif defined(Q_OS_MACOS)
if (eventType == "mac_generic_NSEvent" {
MSG * event = reinterpret_cast<NSEvent*>(message);
assert(event != nullptr);
// ...
}
#elif defined(Q_OS_WINDOWS)
if (eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG") {
MSG* event = reinterpret_cast<MSG*>(message);
assert(event != nullptr);
if(event->message == WM_KEYDOWN || event->message == WM_KEYUP ) {
if( event->wParam == mKey ) {
// keep stop_it to false for the key being processed
// but tells the 'next client' that he doesn't need
// to process it a second time.
mAction();
}
}
}
#else
#error "Yet unsupported OS"
#endif
return stop_it;
}
};
CFilter mFilter;
public:
explicit CKeyEventFilter(KeyType key, Functor action)
: mFilter(key, action)
{
qApp->installNativeEventFilter(&mFilter);
}
virtual ~CKeyEventFilter()
{
qApp->removeNativeEventFilter(&mFilter);
}
};
{
// Workaround with this stack based object (0x1B = 27 = ascii code for Esc char)
CKeyEventFilter filter(0x1B, []() { CMainWindow::win()->setSkipEscape(); } );
// Example of purpose: if dialog is left with the Escape Key,
// CMainWindow::setSkipEscape() in the lambda above will be called
QTableWidgetItem* cell = ui->config_children_table->item(row, col);
cell->setSelected(false);
QColorDialog dialog(this);
dialog.setCurrentColor(cell->background().color());
dialog.exec();
if( dialog.result() == QDialog::Accepted ) {
cell->setBackground(QBrush(dialog.currentColor()));
}
}
void CMainWindow::popScreen()
{
// mSkipEscape is initialized to false in CMainWindow's constructor
// and set by CMainWindow::setSkipEscape() in the lambda above.
if( mSkipEscape ) {
mSkipEscape = false;
} else {
if( ! mScreenStack.empty()) {
EScreens screen = mScreenStack.top();
mScreenStack.pop();
this->goScreen(screen);
}
}
}