我正在努力研究如何使标题中的所有内容在特定情况下可以协同工作。我在这里使用PyQt5,但可以随意使用常规C ++ Qt进行响应,因为我可以很轻松地进行翻译。
我正在尝试通过以下方式创建UI:
一种主要形式(继承自QWidget
,也可以使用QMainWindow
)
主表单应包含一个垂直放置的QSplitter
,顶部包含一个QTextEdit
,并包含一个自定义类(从QLabel
继承),以显示占据其余空间的图像。
顶部的QTextEdit
应该默认为大约3行文本高,但是应该通过QSplitter
将该大小调整为任意合理的极限。
自定义类应在给定可用空间的同时将图像调整为尽可能大的尺寸,同时保持纵横比。
当然,棘手的部分是使所有内容正确调整大小,具体取决于用户的监视器大小以及如何移动表单。我需要它在小到约1,000 px宽,也许大到3,000+ px宽的屏幕上运行。
这是我到目前为止的内容:
# QSplitter3.py import cv2 import numpy as np from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QGridLayout, QSizePolicy, \ QFrame, QTabWidget, QTextEdit, QSplitter from PyQt5.QtGui import QImage, QPixmap, QPainter from PyQt5.Qt import Qt from PyQt5.Qt import QPoint def main(): app = QApplication([]) screenSize = app.primaryScreen().size() print('screenSize = ' + str(screenSize.width()) + ', ' + str(screenSize.height())) mainForm = MainForm(screenSize) mainForm.show() app.exec() # end function class MainForm(QWidget): def __init__(self, screenSize): super().__init__() # set the title and size of the Qt QWidget window self.setWindowTitle('Qt Window') self.setGeometry(screenSize.width() * 0.2, screenSize.height() * 0.2, screenSize.width() * 0.5 , screenSize.height() * 0.7) # declare a QTextEdit to show user messages at the top, set the font size, height, and read only property self.txtUserMessages = QTextEdit() self.setFontSize(self.txtUserMessages, 14) self.txtUserMessages.setReadOnly(True) # make the min height of the text box about 2 lines of text high self.txtUserMessages.setMinimumHeight(self.getTextEditHeightForNLines(self.txtUserMessages, 2)) # populate the user messages text box with some example text self.txtUserMessages.append('message 1') self.txtUserMessages.append('message 2') self.txtUserMessages.append('message 3') self.txtUserMessages.append('stuff here') self.txtUserMessages.append('bla bla bla') self.txtUserMessages.append('asdasdsadds') # instantiate the custom ImageWidget class below to show the image self.imageWidget = ImageWidget() self.imageWidget.setMargin(0) self.imageWidget.setContentsMargins(0, 0, 0, 0) self.imageWidget.setScaledContents(True) self.imageWidget.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.imageWidget.setAlignment(Qt.AlignCenter) # declare the splitter, then add the user message text box and tab widget self.splitter = QSplitter(Qt.Vertical) self.splitter.addWidget(self.txtUserMessages) self.splitter.addWidget(self.imageWidget) defaultTextEditHeight = self.getTextEditHeightForNLines(self.txtUserMessages, 3) print('defaultTextEditHeight = ' + str(defaultTextEditHeight)) # How can I use defaultTextEditHeight height here, but still allow resizing ?? # I really don't like this line, the 1000 is a guess and check that may only work with one screen size !!! self.splitter.setSizes([defaultTextEditHeight, 1000]) # Should setStretchFactor be used here ?? This does not seem to work # self.splitter.setStretchFactor(0, 0) # self.splitter.setStretchFactor(1, 1) # What about sizeHint() ?? Should that be used here, and if so, how ?? # set the main form's layout to the QGridLayout self.gridLayout = QGridLayout() self.gridLayout.addWidget(self.splitter) self.setLayout(self.gridLayout) # open the two images in OpenCV format self.openCvImage = cv2.imread('image.jpg') if self.openCvImage is None: print('error opening image') return # end if # convert the OpenCV image to QImage self.qtImage = openCvImageToQImage(self.openCvImage) # show the QImage on the ImageWidget self.imageWidget.setPixmap(QPixmap.fromImage(self.qtImage)) # end function def setFontSize(self, widget, fontSize): font = widget.font() font.setPointSize(fontSize) widget.setFont(font) # end function def getTextEditHeightForNLines(self, textEdit, numLines): fontMetrics = textEdit.fontMetrics() rowHeight = fontMetrics.lineSpacing() rowHeight = rowHeight * 1.21 textEditHeight = int(numLines * rowHeight) return textEditHeight # end function # end class def openCvImageToQImage(openCvImage): # get the height, width, and num channels of the OpenCV image, then compute the byte value height, width, numChannels = openCvImage.shape byteValue = numChannels * width # make the QImage from the OpenCV image qtImage = QImage(openCvImage.data, width, height, byteValue, QImage.Format_RGB888).rgbSwapped() return qtImage # end function class ImageWidget(QLabel): def __init__(self): super(QLabel, self).__init__() # end function def setPixmap(self, pixmap): self.pixmap = pixmap # end function def paintEvent(self, event): size = self.size() painter = QPainter(self) point = QPoint(0, 0) scaledPixmap = self.pixmap.scaled(size, Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation) point.setX((size.width() - scaledPixmap.width()) / 2) point.setY((size.height() - scaledPixmap.height()) / 2) painter.drawPixmap(point, scaledPixmap) # end function # end class if __name__ == '__main__': main()
[当前,我正在2560x1440屏幕上进行测试,并输入了魔法
1000
,它可以在这种屏幕尺寸上工作,但是我真的不喜欢硬编码的1000
。我怀疑这部分缺少代码的区域:
# declare the splitter, then add the user message text box and tab widget self.splitter = QSplitter(Qt.Vertical) self.splitter.addWidget(self.txtUserMessages) self.splitter.addWidget(self.imageWidget) defaultTextEditHeight = self.getTextEditHeightForNLines(self.txtUserMessages, 3) print('defaultTextEditHeight = ' + str(defaultTextEditHeight)) # How can I use defaultTextEditHeight height here, but still allow resizing ?? # I really don't like this line, the 1000 is a guess and check that may only work with one screen size !!! self.splitter.setSizes([defaultTextEditHeight, 1000]) # Should setStretchFactor be used here ?? This does not seem to work # self.splitter.setStretchFactor(0, 0) # self.splitter.setStretchFactor(1, 1) # What about sizeHint() ?? Should that be used here, and if so, how ?? # set the main form's layout to the QGridLayout self.gridLayout = QGridLayout() self.gridLayout.addWidget(self.splitter)
使用硬编码1000并在此特定屏幕上运行良好:
[重申(希望更加清楚),我试图按照以下步骤删除硬编码的1000和命令Qt:
我已经尝试了标题中提到的所有内容的组合以及到目前为止的这篇文章,但是我无法获得此功能,除非使用硬编码的1000,否则可能无法在其他版本上使用屏幕尺寸。
如何删除硬编码的1000并修改以上内容以实现预期的功能?
我正在努力研究如何使标题中的所有内容在特定情况下可以协同工作。我在这里使用PyQt5,但是可以使用常规C ++ Qt进行响应,因为我可以翻译...
在我的解决方案中,我将不考虑opencv的部分,因为它增加了不必要的复杂性。