根据用户输入绘制一条线

Posted

技术标签:

【中文标题】根据用户输入绘制一条线【英文标题】:Drawing a line depending on user input 【发布时间】:2020-02-06 08:32:34 【问题描述】:

关于 PyQt5 的使用,我有以下问题: 我在 QtDesigner 和 PyQt5 中创建了一个带有标签的 GUI(这是一个 png - 带有通过蓝线和绿线连接的站点的地图)、一个 textEdit 和一个按钮。

现在,我想在 textEdit 中输入一个介于 1 和 4 之间的数字。根据用户输入,附加图像中的部分蓝线应以红色绘制。

我想一个例子解释得更好:如果TextEdit中的用户输入是2并且点击了pushButton,那么从S1到S3的蓝线应该被绘制成红色。如果TextEdit中的用户输入为1,再次点击pushButton,S1到S2的蓝线会被画成红色,所以S2到S3的红线又会变成蓝色。

ma​​pDrawer.py

from PyQt5 import uic
from PyQt5.QtWidgets import QLabel, QMainWindow, QApplication, QWidget, QVBoxLayout
from PyQt5.QtGui import QPixmap
import sys


class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()  # Call the inherited classes __init__ method
        uic.loadUi('DesignerGUI.ui', self)  # Load the .ui file
        self.setWindowTitle("GUI for user defined track drawing")

        pixmap = QPixmap('mapRail.png')
        self.pic_label.setPixmap(pixmap)
        self.pic_label.setScaledContents(True)

        self.show()  # Show the GUI


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

DesignerGUI.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>577</width>
    <height>347</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <item>
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeType">
         <enum>QSizePolicy::Fixed</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>5</width>
          <height>30</height>
         </size>
        </property>
       </spacer>
      </item>
      <item>
       <widget class="QLabel" name="label">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>30</height>
         </size>
        </property>
        <property name="font">
         <font>
          <pointsize>12</pointsize>
         </font>
        </property>
        <property name="text">
         <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#0055ff;&quot;&gt;Blue Line&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QTextEdit" name="textEdit">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>0</height>
         </size>
        </property>
        <property name="maximumSize">
         <size>
          <width>11515151</width>
          <height>30</height>
         </size>
        </property>
        <property name="font">
         <font>
          <pointsize>12</pointsize>
         </font>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="pushButton">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>30</height>
         </size>
        </property>
        <property name="font">
         <font>
          <pointsize>12</pointsize>
         </font>
        </property>
        <property name="text">
         <string>PushButton</string>
        </property>
       </widget>
      </item>
      <item>
       <spacer name="horizontalSpacer_2">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeType">
         <enum>QSizePolicy::Fixed</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>5</width>
          <height>30</height>
         </size>
        </property>
       </spacer>
      </item>
     </layout>
    </item>
    <item>
     <widget class="QLabel" name="pic_label">
      <property name="sizePolicy">
       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
      <property name="minimumSize">
       <size>
        <width>183</width>
        <height>50</height>
       </size>
      </property>
      <property name="maximumSize">
       <size>
        <width>1460</width>
        <height>400</height>
       </size>
      </property>
      <property name="text">
       <string>TextLabel</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>577</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

【问题讨论】:

图像总是一样的吗?如果没有,这些图像是如何创建的? 所示示例非常简化。在最终的 GUI 中,我想有几张地图,它们有更多的车站和线路,如示例中所示。未更改的图像/地图提供给用户 - 不是 GUI 的一部分。我的意思是我还可以制作很多图片,涵盖所有可能的用户输入,但这会导致很多图片(大数据量)并且需要大量的手动工作。我只是认为有一种方法可以自动执行此操作。 您的问题可能有几种可能的方法,这完全取决于这些电路的管理或创建方式。如果有一种方法可以访问图形对象(形状、位置、颜色),并且最重要的是,可以参考您需要更改的那些,您可以使用自定义小部件并覆盖 paintEvent 自己绘制电路.如果它们是 svg(并且它们的内部结构允许),则您可以打开它们并更改颜色(但这会更棘手)。但如果它们是普通的光栅图像,你别无选择,只能创建它们。 【参考方案1】:

由于您使用 .png 来显示您的网络,因此创建单独的 .png 可能是最简单的,每个选项一个,并相应地更改像素图。例如,考虑以下四个我保存为“squares0.png”到“squares3.png”的图像。

要在按下按钮时更改显示的像素图,您可以执行类似的操作

class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()  # Call the inherited classes __init__ method
        uic.loadUi('laser.ui', self)  # Load the .ui file
        self.setWindowTitle("GUI for user defined track drawing")
        self.pixmaps = '1':'squares1.png', '2':'squares2.png', '3':'squares3.png'
        self.default_pixmap = 'squares0.png'
        self.pic_label.setScaledContents(True)

        self.pushButton.clicked.connect(self.set_pixmap)
        self.set_pixmap()

        self.show()  # Show the GUI

    def set_pixmap(self, strng = ''):
        text = self.textEdit.toPlainText().strip()
        file = self.pixmaps.get(text, self.default_pixmap)
        pixmap = QPixmap(file)
        self.pic_label.setPixmap(pixmap)

顺便说一句,为了获得更加用户友好的体验,您可以考虑使用QSpinBoxQComboBox 而不是QTextEdit 来输入数字。

【讨论】:

非常感谢您提出的解决方案和关于用户友好性的建议。我也在考虑这种解决方案。不幸的是,在考虑大量地图和可能性时,需要进行大量手动工作。但无论如何这会起作用:),也许还有其他方法?

以上是关于根据用户输入绘制一条线的主要内容,如果未能解决你的问题,请参考以下文章

在绘制的点之间绘制一条线

如何用CoreGraphics绘制一条线,它的线索将开始以一定的长度消失?

如何根据用户在Android Studio(Java)中输入的条件显示可绘制对象

Python边缘提取如何拟合一条线

当手指在 iPhone 上移动时如何在图像顶部画一条线

根据用户输入的字符数循环列表