QT模态窗口和禁用父项工具栏

时间:2021-07-16 08:44:38

I am developing a project using Qt4 and I have run into a slight issue. I am creating a modal window from the main window. I want this to disable the toolbar at the top. I have a menu item that spawns the modal from the menu. What I want is that when the modal is spawned that menus is disabled. I have tried using the setEnabled(false) function but that doesn't reset it.

我正在使用Qt4开发一个项目,我遇到了一个小问题。我正在从主窗口创建一个模态窗口。我希望这能禁用顶部的工具栏。我有一个菜单项,从菜单中生成模态。我想要的是当产生模态时菜单被禁用。我尝试过使用setEnabled(false)函数,但是没有重置它。

Here is the code:

这是代码:

void Main_Screen::Create_ViPro()
{
   std::auto_ptr<ViPro_Dialog> modal(new ViPro_Dialog(this));
   modal->show();
   modal->exec();
}

So It is just a simple class that is triggered when a menu item is selected. I feel that the problem stems from the fact that i'm setting the parent to the main screen, however I don't know how to create a modal without a parent(it doesn't make sense to do that). Is there a way to disable the parents toolbar from the child? The only thing I have seen so far is _fileMenu->setEnabled(false); That works as long as I don't create the modal, but as soon as that is spawned, the menu works again. I'm totally lost. Thanks in advance

所以这只是一个选择菜单项时触发的简单类。我觉得问题源于我将父设置到主屏幕的事实,但是我不知道如何在没有父设备的情况下创建模态(这样做没有意义)。有没有办法禁用孩子的父母工具栏?到目前为止我唯一看到的是_fileMenu-> setEnabled(false);只要我不创建模态,这就有效,但只要生成模式,菜单就会再次运行。我完全迷失了。提前致谢

Edit as Patrice

编辑为Patrice

Here is the constructor

这是构造函数

    Main_Screen::Main_Screen(QWidget* parent /*= NULL*/) 
                        : QMainWindow(parent),
                          _newProj(new QAction(tr("New &ViPro"), this)),
                          _fileMenu(menuBar()->addMenu(tr("&File")))
{    
  //create slot for creating a new project
  connect(_newProj.get(), SIGNAL(triggered()), this, SLOT(Create_ViPro()));
  _fileMenu->addAction(_newProj.get());
  //if i do this then setEnabled(false) works perfectly and i can't access the menu
  Create_ViPro()
}

So the function is signaled by triggering the newproject action. If i call the function directly from within the constructor it disables it as you stated patrice, however, if I have the function called via the trigger, it doesn't disable it. Am I handling the signal / slot mechanism wrong? Thanks again.

因此,通过触发newproject动作来发出信号。如果我直接从构造函数中调用该函数,它会像你所说的patrice一样禁用它,但是,如果我有通过触发器调用的函数,它不会禁用它。我处理信号/插槽机制错了吗?再次感谢。

Another example, if I make the function create_vipro() as below

另一个例子,如果我将函数create_vipro()如下所示

void Main_Screen::Create_ViPro()
{
     _fileMenu->setEnabled(false);
}

The file menu isn't disabled when I trigger the event, so it must have nothing to do with the modal itself, but instead how signals are handled.

触发事件时,文件菜单未被禁用,因此它必须与模态本身无关,而是与信号的处理方式无关。

2 个解决方案

#1


0  

Since child is a modal dialog main screen can't react to event. But you can disable the toolbar (or menubar) before creating the modal dialog and enable it as soon as you leave the exec function:

由于子是模态对话框主屏幕无法对事件作出反应。但您可以在创建模式对话框之前禁用工具栏(或菜单栏),并在离开exec函数后立即启用它:

void Main_Screen::Create_ViPro()
{
   _fileMenu->setEnabled(false);

   std::auto_ptr<ViPro_Dialog> modal(new ViPro_Dialog(this));
   modal->show();
   modal->exec(); // Will stay here until you close the modal dialog

   _fileMenu->setEnabled(true);
}

if ViPro_Dialog is really a modal dialog it will works.

如果ViPro_Dialog真的是一个模态对话框,它将起作用。

Another thing, since ViPro_Dialog is modal you can declare it locally without using auto_ptr:

另一件事,因为ViPro_Dialog是模态的,你可以在不使用auto_ptr的情况下在本地声明它:

void Main_Screen::Create_ViPro()
{
   _fileMenu->setEnabled(false);

   ViPro_Dialog modal(this);
   modal.show();
   modal.exec(); // Will stay here until you close the modal dialog

   _fileMenu->setEnabled(true);
}

EDIT:

I guess (I can't test at work) that you can't enable/disable menu when it is executing a QAction. Signal is calling slots sequentially so QAction is busy when you try to disable the menu. Try this:

我猜(我无法在工作中测试)在执行QAction时无法启用/禁用菜单。信号正在顺序调用插槽,因此当您尝试禁用菜单时QAction正忙。试试这个:

  1. In Main Screen, create a slot with one boolean parameter that enable/disable menubar. Just call the setEnabled function
  2. 在主屏幕中,创建一个带有一个布尔参数的插槽,用于启用/禁用菜单栏。只需调用setEnabled函数即可

  3. In ViPro_Dialog, emit a signal with a boolean parameter (false at startup, true at validation)
  4. 在ViPro_Dialog中,使用布尔参数发出信号(启动时为false,验证时为true)

  5. In Create_ViPro, once dialog created, connect the new signal with the slot, exec dialog and don't forget to disconnect slot from signal:
  6. 在Create_ViPro中,创建对话框后,将新信号与插槽,exec对话框连接,不要忘记将插槽与信号断开:

void Main_Screen::Create_ViPro() { ViPro_Dialog modal(this);

void Main_Screen :: Create_ViPro(){ViPro_Dialog modal(this);

// Connect signal/slot

//连接信号/插槽

modal.show(); modal.exec(); // Will stay here until you close the modal dialog

modal.show(); modal.exec(); //将关闭模态对话框

// Disconnect signal/slot }

//断开信号/插槽}

This can achieve what you want

这可以实现你想要的

EDIT2

You are doing a mistake when using modal dialog. There's a conflict between show() and exec(). When you are displaying modal dialog you don't need to disable other windows: it's automatically done by modal status of the dialog. There are many modal depth: http://qt-project.org/doc/qt-4.8/qt.html#WindowModality-enum. So your code should be:

使用模态对话框时出错了。 show()和exec()之间存在冲突。当您显示模态对话框时,您不需要禁用其他窗口:它由对话框的模态状态自动完成。有许多模态深度:http://qt-project.org/doc/qt-4.8/qt.html#WindowModality-enum。所以你的代码应该是:

void Main_Screen::Create_ViPro()
{
   ViPro_Dialog modal(this);

   // modal.setWindowModality(Qt::WindowModal); // Uncomment this line if you want to only disable parent

   modal.exec();
}

Read this for more detail: http://qt-project.org/doc/qt-4.8/QDialog.html#details.

阅读本文以获取更多详细信息:http://qt-project.org/doc/qt-4.8/QDialog.html#details。

#2


0  

Using exec() doesn't just create a modal dialog, it also suspends most of the regular event handling, and only handles events in the dialog that is in exec(). This may include some UI updates (like the transitions from enabled to disabled), but I'm not positive. A better way to handle this might be to explicitly set the dialog modal, but allow the regular event loop to continue, something like this:

使用exec()不只是创建一个模态对话框,它还会暂停大多数常规事件处理,并且只处理exec()中对话框中的事件。这可能包括一些UI更新(如从启用到禁用的转换),但我不是积极的。处理此问题的更好方法可能是显式设置对话框模态,但允许常规事件循环继续,如下所示:

void Main_Screen::Create_ViPro()
{
   ViPro_Dialog* modal = new ViPro_Dialog(this);
   modal->setModal(true);
   modal->show();
}

That code will still not visually disable the toolbar or menubar, but they should be unresponsive. To disable them, you could try combining this with Patrice Bernassola's answer.

该代码仍然不会在视觉上禁用工具栏或菜单栏,但它们应该没有响应。要禁用它们,您可以尝试将其与Patrice Bernassola的答案结合起来。

#1


0  

Since child is a modal dialog main screen can't react to event. But you can disable the toolbar (or menubar) before creating the modal dialog and enable it as soon as you leave the exec function:

由于子是模态对话框主屏幕无法对事件作出反应。但您可以在创建模式对话框之前禁用工具栏(或菜单栏),并在离开exec函数后立即启用它:

void Main_Screen::Create_ViPro()
{
   _fileMenu->setEnabled(false);

   std::auto_ptr<ViPro_Dialog> modal(new ViPro_Dialog(this));
   modal->show();
   modal->exec(); // Will stay here until you close the modal dialog

   _fileMenu->setEnabled(true);
}

if ViPro_Dialog is really a modal dialog it will works.

如果ViPro_Dialog真的是一个模态对话框,它将起作用。

Another thing, since ViPro_Dialog is modal you can declare it locally without using auto_ptr:

另一件事,因为ViPro_Dialog是模态的,你可以在不使用auto_ptr的情况下在本地声明它:

void Main_Screen::Create_ViPro()
{
   _fileMenu->setEnabled(false);

   ViPro_Dialog modal(this);
   modal.show();
   modal.exec(); // Will stay here until you close the modal dialog

   _fileMenu->setEnabled(true);
}

EDIT:

I guess (I can't test at work) that you can't enable/disable menu when it is executing a QAction. Signal is calling slots sequentially so QAction is busy when you try to disable the menu. Try this:

我猜(我无法在工作中测试)在执行QAction时无法启用/禁用菜单。信号正在顺序调用插槽,因此当您尝试禁用菜单时QAction正忙。试试这个:

  1. In Main Screen, create a slot with one boolean parameter that enable/disable menubar. Just call the setEnabled function
  2. 在主屏幕中,创建一个带有一个布尔参数的插槽,用于启用/禁用菜单栏。只需调用setEnabled函数即可

  3. In ViPro_Dialog, emit a signal with a boolean parameter (false at startup, true at validation)
  4. 在ViPro_Dialog中,使用布尔参数发出信号(启动时为false,验证时为true)

  5. In Create_ViPro, once dialog created, connect the new signal with the slot, exec dialog and don't forget to disconnect slot from signal:
  6. 在Create_ViPro中,创建对话框后,将新信号与插槽,exec对话框连接,不要忘记将插槽与信号断开:

void Main_Screen::Create_ViPro() { ViPro_Dialog modal(this);

void Main_Screen :: Create_ViPro(){ViPro_Dialog modal(this);

// Connect signal/slot

//连接信号/插槽

modal.show(); modal.exec(); // Will stay here until you close the modal dialog

modal.show(); modal.exec(); //将关闭模态对话框

// Disconnect signal/slot }

//断开信号/插槽}

This can achieve what you want

这可以实现你想要的

EDIT2

You are doing a mistake when using modal dialog. There's a conflict between show() and exec(). When you are displaying modal dialog you don't need to disable other windows: it's automatically done by modal status of the dialog. There are many modal depth: http://qt-project.org/doc/qt-4.8/qt.html#WindowModality-enum. So your code should be:

使用模态对话框时出错了。 show()和exec()之间存在冲突。当您显示模态对话框时,您不需要禁用其他窗口:它由对话框的模态状态自动完成。有许多模态深度:http://qt-project.org/doc/qt-4.8/qt.html#WindowModality-enum。所以你的代码应该是:

void Main_Screen::Create_ViPro()
{
   ViPro_Dialog modal(this);

   // modal.setWindowModality(Qt::WindowModal); // Uncomment this line if you want to only disable parent

   modal.exec();
}

Read this for more detail: http://qt-project.org/doc/qt-4.8/QDialog.html#details.

阅读本文以获取更多详细信息:http://qt-project.org/doc/qt-4.8/QDialog.html#details。

#2


0  

Using exec() doesn't just create a modal dialog, it also suspends most of the regular event handling, and only handles events in the dialog that is in exec(). This may include some UI updates (like the transitions from enabled to disabled), but I'm not positive. A better way to handle this might be to explicitly set the dialog modal, but allow the regular event loop to continue, something like this:

使用exec()不只是创建一个模态对话框,它还会暂停大多数常规事件处理,并且只处理exec()中对话框中的事件。这可能包括一些UI更新(如从启用到禁用的转换),但我不是积极的。处理此问题的更好方法可能是显式设置对话框模态,但允许常规事件循环继续,如下所示:

void Main_Screen::Create_ViPro()
{
   ViPro_Dialog* modal = new ViPro_Dialog(this);
   modal->setModal(true);
   modal->show();
}

That code will still not visually disable the toolbar or menubar, but they should be unresponsive. To disable them, you could try combining this with Patrice Bernassola's answer.

该代码仍然不会在视觉上禁用工具栏或菜单栏,但它们应该没有响应。要禁用它们,您可以尝试将其与Patrice Bernassola的答案结合起来。