当前位置: 首页 > 面试题库 >

使用视图的委托方法(PySide / Qt / PyQt)将QMainWindow中的动作连接起来

柯建修
2023-03-14
问题内容

我有QTreeView来自的显示数据QStandardItemModel。树的一列显示有一个委托,该委托使用户可以编辑和显示富文本。下面是一个SSCCE,它将编辑内容限制为粗体(使用键盘快捷键)。

当用户编辑其中一项时,如何设置它,以便除了使用键盘快捷键(CTRL-B)切换粗体之外,用户还可以使用工具栏图标进行切换?

在此处输入图片说明

到目前为止,键盘快捷键的效果很好(您可以双击,编辑文本,并且CTRL-B将切换为粗体)。但是,我还没有弄清楚如何将工具栏中的粗体按钮连接到适当的插槽:

    self.boldTextAction.triggered.connect(self.emboldenText)

我只有坐在那里什么都不做的地方:

def emboldenText(self):
    print "Make selected text bold...How do I do this?"

如果主窗口的中央小部件是文本编辑器,事情将会很容易:我可以直接调用文本编辑器的toggle
bold方法。不幸的是,当用户双击开始编辑树时,文本编辑器仅由树视图的委托临时生成。

也就是说,我们有这种复杂的关系:

QMainWindow-> QTreeView-> Delegate.CreateEditor-> QTextEdit.toggleBold()

如何从主窗口中访问toggleBold()以供工具栏操作使用,尤其是考虑到编辑器仅在用户打开时临时创建?

我意识到这可能不像Python / OOP问题那样是PySide /
Qt问题,因此我加入了其他可能相关的标签。改善我的单词选择/专业术语的任何帮助也将不胜感激。

社会科学中心

#!/usr/bin/env python

import platform
import sys
from PySide import QtGui, QtCore


class MainTree(QtGui.QMainWindow):
    def __init__(self, tree, parent = None):
        QtGui.QMainWindow.__init__(self)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose) 
        self.setCentralWidget(tree)
        self.createStatusBar()
        self.createBoldAction()
        self.createToolbar()
        self.tree = tree
        #self.htmlDelegate = self.tree.itemDelegateForColumn(1)

    def createStatusBar(self):                          
        self.status = self.statusBar()
        self.status.setSizeGripEnabled(False)
        self.status.showMessage("In editor, keyboard to toggle bold")

    def createToolbar(self):
        self.textToolbar = self.addToolBar("Text actions")
        self.textToolbar.addAction(self.boldTextAction)

    def createBoldAction(self):
        self.boldTextAction = QtGui.QAction("Bold", self)
        self.boldTextAction.setIcon(QtGui.QIcon("boldText.png"))
        self.boldTextAction.triggered.connect(self.emboldenText)
        self.boldTextAction.setStatusTip("Make selected text bold")

    def emboldenText(self):
        print "Make selected text bold...How do I do this? It's stuck in RichTextLineEdit"

class HtmlTree(QtGui.QTreeView):
    def __init__(self, parent = None):    
        QtGui.QTreeView.__init__(self)
        model = QtGui.QStandardItemModel()
        model.setHorizontalHeaderLabels(['Task', 'Priority'])
        rootItem = model.invisibleRootItem()
        item0 = [QtGui.QStandardItem('Sneeze'), QtGui.QStandardItem('Low')]
        item00 = [QtGui.QStandardItem('Tickle nose'), QtGui.QStandardItem('Low')]
        item1 = [QtGui.QStandardItem('Get a job'), QtGui.QStandardItem('<b>High</b>')]
        item01 = [QtGui.QStandardItem('Call temp agency'), QtGui.QStandardItem('<b>Extremely</b> <i>high</i>')]
        rootItem.appendRow(item0)
        item0[0].appendRow(item00) 
        rootItem.appendRow(item1)
        item1[0].appendRow(item01)
        self.setModel(model)
        self.expandAll()
        self.resizeColumnToContents(0)
        self.setToolTip("Use keyboard to toggle bold")
        self.setItemDelegate(HtmlPainter(self))

class HtmlPainter(QtGui.QStyledItemDelegate):
    def __init__(self, parent=None):
        QtGui.QStyledItemDelegate.__init__(self, parent)

    def paint(self, painter, option, index):
        if index.column() == 1: 
            text = index.model().data(index) #default role is display (for edit consider fixing Valign prob)
            palette = QtGui.QApplication.palette()
            document = QtGui.QTextDocument()
            document.setDefaultFont(option.font)
            #Set text (color depends on whether selected)
            if option.state & QtGui.QStyle.State_Selected:  
                displayString = "<font color={0}>{1}</font>".format(palette.highlightedText().color().name(), text) 
                document.setHtml(displayString)
            else:
                document.setHtml(text)
            #Set background color
            bgColor = palette.highlight().color() if (option.state & QtGui.QStyle.State_Selected)\
                     else palette.base().color()
            painter.save()

            painter.fillRect(option.rect, bgColor)
            document.setTextWidth(option.rect.width())
            offset_y = (option.rect.height() - document.size().height())/2
            painter.translate(option.rect.x(), option.rect.y() + offset_y) 
            document.drawContents(painter)
            painter.restore()
        else:
            QtGui.QStyledItemDelegate.paint(self, painter, option, index)

    def sizeHint(self, option, index):
        fm = option.fontMetrics
        if index.column() == 1:
            text = index.model().data(index)
            document = QtGui.QTextDocument()
            document.setDefaultFont(option.font)
            document.setHtml(text)
            return QtCore.QSize(document.idealWidth() + 5, fm.height())
        return QtGui.QStyledItemDelegate.sizeHint(self, option, index)


    def createEditor(self, parent, option, index):
        if index.column() == 1:
            editor = RichTextLineEdit(parent)
            editor.returnPressed.connect(self.commitAndCloseEditor)
            return editor
        else:
            return QtGui.QStyledItemDelegate.createEditor(self, parent, option,
                                                    index)

    def commitAndCloseEditor(self):
        editor = self.sender()
        if isinstance(editor, (QtGui.QTextEdit, QtGui.QLineEdit)):
            self.commitData.emit(editor)
            self.closeEditor.emit(editor, QtGui.QAbstractItemDelegate.NoHint)


class RichTextLineEdit(QtGui.QTextEdit):

    returnPressed = QtCore.Signal()

    def __init__(self, parent=None):
        QtGui.QTextEdit.__init__(self, parent)
        self.setLineWrapMode(QtGui.QTextEdit.NoWrap)
        self.setTabChangesFocus(True)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        fontMetrics = QtGui.QFontMetrics(self.font())
        h = int(fontMetrics.height() * (1.4 if platform.system() == "Windows"
                                   else 1.2))
        self.setMinimumHeight(h)
        self.setMaximumHeight(int(h * 1.2))
        self.setToolTip("Press <b>Ctrl+b</b> to toggle bold")

    def toggleBold(self):
        self.setFontWeight(QtGui.QFont.Normal
                if self.fontWeight() > QtGui.QFont.Normal else QtGui.QFont.Bold)

    def sizeHint(self):
        return QtCore.QSize(self.document().idealWidth() + 5,
                     self.maximumHeight())

    def minimumSizeHint(self):
        fm = QtGui.QFontMetrics(self.font())
        return QtCore.QSize(fm.width("WWWW"), self.minimumHeight())

    def keyPressEvent(self, event):
        '''This just handles all keyboard shortcuts, and stops retun from returning'''
        if event.modifiers() & QtCore.Qt.ControlModifier:
            handled = False
            if event.key() == QtCore.Qt.Key_B:
                self.toggleBold()
                handled = True
            if handled:
                event.accept()
                return
        if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
            self.returnPressed.emit()
            event.accept()
        else:
            QtGui.QTextEdit.keyPressEvent(self, event)


def main():
    app = QtGui.QApplication(sys.argv)
    myTree = HtmlTree()
    #myTree.show()
    myMainTree = MainTree(myTree)
    myMainTree.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

请注意,对于那些需要“全树体验”的用户,单击工具栏中的按钮,即可将其与脚本放在同一文件夹中(将名称更改为boldText.png

在此处输入图片说明


问题答案:

从设计的角度来看,我认为顶部窗口是一种全局的窗口。您已经描述了一种以这种方式对其进行处理的行为,并且(如ekhumoro所说),几乎需要您向编辑器提供对该顶部窗口的访问。

一个非常简单的方法是调用parent.window()createEditor方法。也许像这样:

parent.window().boldTextAction.triggered.connect(editor.toggleBold)

这似乎对我有用。



 类似资料:
  • 本文向大家介绍PyQt 图解Qt Designer工具的使用方法,包括了PyQt 图解Qt Designer工具的使用方法的使用技巧和注意事项,需要的朋友参考一下 前言 Qt Designer是PyQt程序UI界面的实现工具,Qt Designer工具使用简单,可以通过拖拽和点击完成复杂界面设计,并且设计完成的.ui程序可以转换成.py文件供python程序调用。本文主要通过用户登录需求描述Qt

  • 我在Xcode6中创建了新项目,并将旧文件添加到这个项目中(旧文件在xcode5中创建),但发生的事情是一切正常,但“didupdateTolocation”委托方法没有调用,我也使用了“didupdateLocations”委托方法,但两者都不工作。我从旧文件中使用的代码,但核心位置框架是从Xcode6中添加的,我不知道我缺少什么,请任何人指导我获得解决方案。

  • 本文向大家介绍C#中委托(Delegates)的使用方法详解,包括了C#中委托(Delegates)的使用方法详解的使用技巧和注意事项,需要的朋友参考一下 1. 委托是什么? 其实,我一直思考如何讲解委托,才能把委托说得更透彻。说实话,每个人都委托都有不同的见解,因为看问题的角度不同。个人认为,可以从以下2点来理解:  (1) 从数据结构来讲,委托是和类一样是一种用户自定义类型。  (2) 从设计

  • 本文向大家介绍VS2019中QT连接及使用的方法步骤,包括了VS2019中QT连接及使用的方法步骤的使用技巧和注意事项,需要的朋友参考一下 qt连接VS 连接前提是在下载qt的时候将 MSVC 2017装上 点击扩展 选择管理扩展 搜索qt 选择下载 之后下载结束并重新打开后 会弹出一个 QT option 将路径填进去 VS中qt的使用 在qt中可以直接添加信号与槽 在vs中使用是不一样的 直接

  • 本文向大家介绍iOS委托的的作用?相关面试题,主要包含被问及iOS委托的的作用?时的应答技巧和注意事项,需要的朋友参考一下 答案:委托的目的是改变或传递控制链。允许一个类在某些特定时刻通知到其他类,而不需要获取到那些类的指针。可以减少框架复杂度。 另外一点,委托可以理解为java中的回调监听机制的一种类似。

  • 本文向大家介绍C#中的委托使用,包括了C#中的委托使用的使用技巧和注意事项,需要的朋友参考一下 从今天开始写关于C#的系列文章,本篇文章主要讲解C#中的委托使用。 委托其实就是一种数据类型,和int,string是一样的概念。 如果要把一个字符串赋值给一个变量,用string声明一个变量即可。如果要把一个方法赋值给一个变量,那么用什么关键字呢?当然就是用委托了,所以用委托声明的变量就可以接受一个方