【发布时间】:2018-11-18 19:32:53
【问题描述】:
我想运行 qt QSyntaxHighlight 示例,但使用 QML 构建窗口,而不是使用 python 代码。虽然我仍然设法这样做,但代码很尴尬,我相信我的 QML 或 API 理解是错误的。
我使用名为 main.qml 的 TextEdits 创建了简单的 QML 文件
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello")
TextEdit {
id: text_view
objectName: "text_view"
x: 0
y: 0
width: parent.width
height: parent.height * 0.8
color: "black"
text: qsTr("long class")
font.pixelSize: 12
anchors.margins: 5
}
TextEdit {
id: text_input
anchors.top: text_view.bottom
width: parent.width
height: parent.height - text_view.height
color: "#ef1d1d"
text: qsTr("")
font.capitalization: Font.MixedCase
font.pixelSize: 12
}
}
然后添加main.py:
#!/bin/python3
import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import QObject
from PyQt5.QtGui import QGuiApplication, QSyntaxHighlighter, QTextDocument
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtQml import QQmlApplicationEngine, qmlRegisterType
class Highlighter(QSyntaxHighlighter):
def __init__(self, parent=None):
super(Highlighter, self).__init__(parent)
keywordFormat = QtGui.QTextCharFormat()
keywordFormat.setForeground(QtCore.Qt.darkBlue)
keywordFormat.setFontWeight(QtGui.QFont.Bold)
keywordPatterns = ["\\bchar\\b", "\\bclass\\b", "\\bconst\\b",
"\\bdouble\\b", "\\benum\\b", "\\bexplicit\\b", "\\bfriend\\b",
"\\binline\\b", "\\bint\\b", "\\blong\\b", "\\bnamespace\\b",
"\\boperator\\b", "\\bprivate\\b", "\\bprotected\\b",
"\\bpublic\\b", "\\bshort\\b", "\\bsignals\\b", "\\bsigned\\b",
"\\bslots\\b", "\\bstatic\\b", "\\bstruct\\b",
"\\btemplate\\b", "\\btypedef\\b", "\\btypename\\b",
"\\bunion\\b", "\\bunsigned\\b", "\\bvirtual\\b", "\\bvoid\\b",
"\\bvolatile\\b"]
self.highlightingRules = [(QtCore.QRegExp(pattern), keywordFormat)
for pattern in keywordPatterns]
classFormat = QtGui.QTextCharFormat()
classFormat.setFontWeight(QtGui.QFont.Bold)
classFormat.setForeground(QtCore.Qt.darkMagenta)
self.highlightingRules.append((QtCore.QRegExp("\\bQ[A-Za-z]+\\b"),
classFormat))
singleLineCommentFormat = QtGui.QTextCharFormat()
singleLineCommentFormat.setForeground(QtCore.Qt.red)
self.highlightingRules.append((QtCore.QRegExp("//[^\n]*"),
singleLineCommentFormat))
self.multiLineCommentFormat = QtGui.QTextCharFormat()
self.multiLineCommentFormat.setForeground(QtCore.Qt.red)
quotationFormat = QtGui.QTextCharFormat()
quotationFormat.setForeground(QtCore.Qt.darkGreen)
self.highlightingRules.append((QtCore.QRegExp("\".*\""), quotationFormat))
functionFormat = QtGui.QTextCharFormat()
functionFormat.setFontItalic(True)
functionFormat.setForeground(QtCore.Qt.blue)
self.highlightingRules.append((QtCore.QRegExp("\\b[A-Za-z0-9_]+(?=\\()"), functionFormat))
self.commentStartExpression = QtCore.QRegExp("/\\*")
self.commentEndExpression = QtCore.QRegExp("\\*/")
def highlightBlock(self, text):
for pattern, format in self.highlightingRules:
expression = QtCore.QRegExp(pattern)
index = expression.indexIn(text)
while index >= 0:
length = expression.matchedLength()
self.setFormat(index, length, format)
index = expression.indexIn(text, index + length)
self.setCurrentBlockState(0)
startIndex = 0
if self.previousBlockState() != 1:
startIndex = self.commentStartExpression.indexIn(text)
while startIndex >= 0:
endIndex = self.commentEndExpression.indexIn(text, startIndex)
if endIndex == -1:
self.setCurrentBlockState(1)
commentLength = len(text) - startIndex
else:
commentLength = endIndex - startIndex + self.commentEndExpression.matchedLength()
self.setFormat(startIndex, commentLength, self.multiLineCommentFormat)
startIndex = self.commentStartExpression.indexIn(text, startIndex + commentLength)
def print_child(el):
print(" " * 2 * print_child.max + "type: {}".format(type(el)))
print(" " * 2 * print_child.max + "name: {}".format(el.objectName()))
print_child.max += 1
try:
for subel in el.children():
print_child(subel)
except TypeError:
pass
print_child.max -= 1
print_child.max = 0
def child_selector(children, ftype):
for ch in children:
if type(ch) is ftype:
return ch
return None
if __name__ in "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.load("main.qml")
print_child(engine.rootObjects()[0])
el = Highlighter(
child_selector(engine.rootObjects()[0].findChild(QObject, "text_view").children(), QTextDocument)
)
engine.quit.connect(app.quit)
sys.exit(app.exec_())
Print child 产生这个输出:
type: <class 'PyQt5.QtGui.QWindow'>
name:
type: <class 'PyQt5.QtCore.QObject'>
name:
type: <class 'PyQt5.QtCore.QObject'>
name: text_view
type: <class 'PyQt5.QtGui.QTextDocument'>
name:
type: <class 'PyQt5.QtGui.QAbstractTextDocumentLayout'>
name:
type: <class 'PyQt5.QtCore.QObject'>
name:
type: <class 'PyQt5.QtGui.QTextFrame'>
name:
type: <class 'PyQt5.QtCore.QObject'>
name:
type: <class 'PyQt5.QtCore.QObject'>
name:
type: <class 'PyQt5.QtGui.QTextDocument'>
name:
type: <class 'PyQt5.QtGui.QAbstractTextDocumentLayout'>
name:
type: <class 'PyQt5.QtCore.QObject'>
name:
type: <class 'PyQt5.QtGui.QTextFrame'>
name:
type: <class 'PyQt5.QtCore.QObject'>
name:
问题:
我已经定义了带有两个 TextEdits 的 Window,而我看到我的 TextEdits 嵌入在额外的 QObject 中(这就是为什么我必须添加
child_selector(...)并且不能直接使用 findChild 输出)为什么会这样还能做得更好吗?是否有一些功能与
findChild(...)相同但使用 id 而不是 objectName?在
engine上使用 findChildren(...) 而没有rootObject()导致None我不明白为什么?
【问题讨论】: