Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
User interface 如何实施;编辑";菜单上有“菜单”;撤消“&引用;削减&引用;粘贴";及;复制;?_User Interface_Qt_Menu_Copy Paste - Fatal编程技术网

User interface 如何实施;编辑";菜单上有“菜单”;撤消“&引用;削减&引用;粘贴";及;复制;?

User interface 如何实施;编辑";菜单上有“菜单”;撤消“&引用;削减&引用;粘贴";及;复制;?,user-interface,qt,menu,copy-paste,User Interface,Qt,Menu,Copy Paste,您好 对于我的一个应用程序,我正在尝试实现一个“编辑”菜单。此菜单通常具有标准条目撤消、剪切、复制和粘贴 默认情况下,此菜单不存在,用户似乎期望它,尤其是在MacOSX上 是否有一种更简单的方法来实现这一点,而不必在每个小部件中手动执行?由于大多数小部件已经通过快捷方式实现了复制/粘贴/撤消机制,因此我想提供一些简单的菜单操作来调用它们 操作应该首先调用具有焦点的任何小部件,然后它们应该将事件向上传递到对象链,我猜 我在Windows、Linux和MacOSX上使用Qt4.6 谢谢 我的印象是编

您好

对于我的一个应用程序,我正在尝试实现一个“编辑”菜单。此菜单通常具有标准条目撤消、剪切、复制和粘贴

默认情况下,此菜单不存在,用户似乎期望它,尤其是在MacOSX上

是否有一种更简单的方法来实现这一点,而不必在每个小部件中手动执行?由于大多数小部件已经通过快捷方式实现了复制/粘贴/撤消机制,因此我想提供一些简单的菜单操作来调用它们

操作应该首先调用具有焦点的任何小部件,然后它们应该将事件向上传递到对象链,我猜

我在Windows、Linux和MacOSX上使用Qt4.6


谢谢

我的印象是编辑菜单适用于中心文档小部件,而不是小部件。我还没有测试过,但是如果您有一个带有QLineEdits的表单,那么编辑菜单(在菜单栏中)是否真的适用于该小部件。不要简单地打开关联菜单或按快捷键来访问这些选项…

完成一半必要的功能就足够容易了。只需在主窗口类中创建编辑菜单以及必要的QActions(复制/粘贴/撤消等),并将它们连接到插槽。在插槽中,模拟正确的按键和释放事件(例如,Ctrl+C表示复制),并将其发送到当前关注的小部件。在代码中,类似以下内容:

MainWindow::MainWindow(...)
{
    ...
    connect( actionCopy, SIGNAL( triggered()), SLOT( copy()));
    ...
}
...
void MainWindow::copy()
{
    QWidget* focused = QApplication::focusWidget();
    if( focused != 0 )
    {
        QApplication::postEvent( focused,
                                 new QKeyEvent( QEvent::KeyPress,
                                                Qt::Key_C,
                                                Qt::ControlModifier ));
        QApplication::postEvent( focused,
                                 new QKeyEvent( QEvent::KeyRelease,
                                                Qt::Key_C,
                                                Qt::ControlModifier ));
}
connect(ui->actionCut, &QAction::triggered, []() {
    QWidget *focusWidget = QApplication::focusWidget();
    QLineEdit *lineEdit = dynamic_cast<QLineEdit*>(focusWidget);
    QTextEdit *textEdit = dynamic_cast<QTextEdit*>(focusWidget);

    if (lineEdit && lineEdit->isEnabled() && !lineEdit->isReadOnly())
        lineEdit->cut();
    else if (textEdit && textEdit->isEnabled() && !textEdit->isReadOnly())
        textEdit->cut();
});
当然,这是一个相当棘手的问题。您需要修改每个目标平台的代码,将键盘快捷键更改为正确的快捷键,并且接收焦点的小部件可能会使用Ctrl+C执行一些意想不到的操作。在我看来,这种方法最糟糕的缺点是无法正确控制编辑菜单项的启用状态。无法从通用小部件查询复制或粘贴操作是否可行


我无法找到这个问题的真正解决方案,如果我发现存在这个问题,我会感到惊讶,因为复制/粘贴功能通常隐藏在类的代码中,而不是通过任何标准的信号集/插槽公开。在今晚的功能性实验之后,我决定忘记我的应用程序中有一个编辑菜单,希望用户知道键盘快捷键,或者使用上下文相关的菜单。

user285740的解决方案对我没有帮助,因为我在我的应用程序中使用了浏览器控件(CEF或WebKit,没关系)

为什么?对于浏览器,
focusWidget()
似乎总是
NULL
,因为
元素不是小部件。我尝试了
postEvent()
到其他小部件,但没有成功。添加带有
QAction::TextHeuristicRole
+标准序列(如
QKeySequence::Copy
)的菜单项也不起作用(我只能将它们连接到我的插槽,不能连接到标准插槽)。Cefclient示例加载一个xib文件,但这不是我的选项,因为Qt从头开始创建一切

最终,我找到了解决办法!从Objective++代码创建相同的菜单项。它们的行为类似于通过
QMenuBar
创建的操作,但是(!)它们可以连接到一些真正的自动操作,如
@selector(copy:)

您可以在这里找到一个示例:,只需从您的ObjC++代码中执行即可


但是,如果在
QApplication::exec()
之前执行此代码,则此代码不起作用。Qt然后以编程方式“重写”主菜单。。。如何解决这个问题?好吧,也许我会添加一些黑客,比如QTimer。如果您不尝试通过QMenuBar添加其他项,则不会这样做。现在没事了!Qt独立菜单。

我能找到的最佳解决方案来自。在我的应用程序中,结果如下所示:

MainWindow::MainWindow(...)
{
    ...
    connect( actionCopy, SIGNAL( triggered()), SLOT( copy()));
    ...
}
...
void MainWindow::copy()
{
    QWidget* focused = QApplication::focusWidget();
    if( focused != 0 )
    {
        QApplication::postEvent( focused,
                                 new QKeyEvent( QEvent::KeyPress,
                                                Qt::Key_C,
                                                Qt::ControlModifier ));
        QApplication::postEvent( focused,
                                 new QKeyEvent( QEvent::KeyRelease,
                                                Qt::Key_C,
                                                Qt::ControlModifier ));
}
connect(ui->actionCut, &QAction::triggered, []() {
    QWidget *focusWidget = QApplication::focusWidget();
    QLineEdit *lineEdit = dynamic_cast<QLineEdit*>(focusWidget);
    QTextEdit *textEdit = dynamic_cast<QTextEdit*>(focusWidget);

    if (lineEdit && lineEdit->isEnabled() && !lineEdit->isReadOnly())
        lineEdit->cut();
    else if (textEdit && textEdit->isEnabled() && !textEdit->isReadOnly())
        textEdit->cut();
});
connect(ui->actionCut,&QAction::triggered,[](){
QWidget*focusWidget=QApplication::focusWidget();
QLineEdit*lineEdit=dynamic_cast(focusWidget);
QTextEdit*textexedit=dynamic_cast(focusWidget);
如果(lineEdit&&lineEdit->isEnabled()&&lineEdit->isReadOnly())
lineEdit->cut();
else if(textEdit&&textEdit->isEnabled()&&!textEdit->isReadOnly())
text编辑->剪切();
});

这真的很糟糕,必须为每个标准菜单项(撤消、重做、剪切、复制、粘贴、删除、全选…)执行,要正确启用/禁用菜单项还需要更多的技巧。这是第一次,在将Cocoa应用程序移植到Qt时,我感觉到Qt显然明显不如Cocoa(在本例中,Qt中似乎根本不存在Cocoa的first responder机制)。不过,我认为它比user285740提出的解决方案要好,后者硬编码特定的键盘动作。YMMV.

对于类似Windows/Linux的窗口管理器来说,这可能是正确的。但是,在OSX上,在屏幕顶部有一个应用程序范围的菜单栏,而不是在每个窗口的顶部。Mac用户希望所选菜单操作对最顶端的窗口和当前具有焦点的小部件产生影响。(选择“粘贴”会将剪贴板中的任何内容粘贴到当前具有焦点的QLineEdit中,等等)