Достижение выравнивания объектов в окне, добавление графиков из другого файла .py - PullRequest
0 голосов
/ 31 марта 2020

Итак, я хотел бы спросить вас о лучшей организации нескольких buttons, TextBox, графов в PyQt5. Ранее мне немного помогали использовать сетку для достижения лучшего выравнивания объекта, который я помещаю в My Window.

Однако финал, который я пытаюсь закодировать, все еще немного далек от происходит.

Вот что я получил до сих пор:

from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import *
import sys


class Okno(QMainWindow):
    def __init__(self):
        super(Okno, self).__init__()
        self.setGeometry(500, 500, 900, 500)
        self.setWindowTitle("My window")
        self.button1 = QtWidgets.QPushButton()
        self.button2 = QtWidgets.QPushButton()
        self.TextBox1 = QLineEdit(self)  # Parameter self - add text box to my Window "Okno"
        self.TextBox2 = QLineEdit(self)
        self.TextBox3 = QLineEdit(self)
        self.TextBox4 = QLineEdit(self)   # Baudrate
        self.TextBox5 = QLineEdit(self)   # Parity
        self.TB_TEMP_IN = QLineEdit(self)   # Temp_IN
        self.TB_TEMP_OUT = QLineEdit(self)   # Temp_OUT
        self.label1 = QtWidgets.QLabel()  # TextBox1, pressure_IN
        self.label2 = QtWidgets.QLabel()
        self.label3 = QtWidgets.QLabel()
        self.label4 = QtWidgets.QLabel()  # TextBox3, pressure_OUT
        self.label_TEMP_IN = QtWidgets.QLabel()
        self.label_TEMP_OUT = QtWidgets.QLabel()
        self.iniUI()

    # Window objects
    def iniUI(self):
        w = QtWidgets.QWidget()
        self.setCentralWidget(w)
        grid = QtWidgets.QGridLayout(w)

        self.button1.setText("Open file")
        self.button1.setMinimumWidth(150)
        self.button1.clicked.connect(self.open_file)
        self.button2.setText("Exit")
        self.button2.clicked.connect(self.close)

        grid.addWidget(self.button1, 10, 0, QtCore.Qt.AlignLeft | QtCore.Qt.AlignBottom)
        grid.addWidget(self.button2, 10, 6, QtCore.Qt.AlignRight | QtCore.Qt.AlignBottom)

        # Text Box
        grid.addWidget(self.TextBox1, 3, 1, QtCore.Qt.AlignCenter | QtCore.Qt.AlignCenter)

        self.TextBox2.setPlaceholderText("Enter port name")
        grid.addWidget(self.TextBox2, 3, 3, QtCore.Qt.AlignCenter | QtCore.Qt.AlignTop)

        grid.addWidget(self.TextBox3, 3, 6, QtCore.Qt.AlignLeft | QtCore.Qt.AlignCenter)

        self.TextBox4.setPlaceholderText("Baudrate")
        grid.addWidget(self.TextBox4, 3, 3, QtCore.Qt.AlignCenter | QtCore.Qt.AlignCenter)

        self.TextBox5.setPlaceholderText("Parity")
        grid.addWidget(self.TextBox5, 3, 3, QtCore.Qt.AlignCenter | QtCore.Qt.AlignBottom)

        grid.addWidget(self.TB_TEMP_IN, 3, 1, QtCore.Qt.AlignCenter | QtCore.Qt.AlignBottom)
        grid.addWidget(self.TB_TEMP_OUT, 3, 6, QtCore.Qt.AlignCenter | QtCore.Qt.AlignBottom)

        # Label (Text Box name)
        self.label1.setText("Pressure_IN")
        grid.addWidget(self.label1, 3, 0, QtCore.Qt.AlignRight| QtCore.Qt.AlignCenter)

        self.label4.setText("Pressure_OUT")
        grid.addWidget(self.label4, 3, 5, QtCore.Qt.AlignRight | QtCore.Qt.AlignCenter)

        self.label_TEMP_IN.setText("Temp_IN")
        grid.addWidget(self.label_TEMP_IN, 3, 0, QtCore.Qt.AlignRight| QtCore.Qt.AlignBottom)

        self.label_TEMP_OUT.setText("Temp_OUT")
        grid.addWidget(self.label_TEMP_OUT, 3, 5, QtCore.Qt.AlignRight | QtCore.Qt.AlignBottom)

        self.label2.setText("Data Input")
        grid.addWidget(self.label2, 0, 0, QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
        self.label2.setStyleSheet('color: red')

        self.label3.setText("Data output")
        grid.addWidget(self.label3, 0, 6, QtCore.Qt.AlignRight | QtCore.Qt.AlignTop)
        self.label3.setStyleSheet('color: blue')

    def open_file(self):
        print("Open file")


def window():
    app = QApplication(sys.argv)
    okno = Okno()
    okno.show()
    sys.exit(app.exec_())


window()

Одна вещь, которую я заметил при добавлении большего количества объектов с помощью Grid, это то, что это трудно организовать. Мне пришлось расширить сетку до 10 x 6, если я правильно понимаю, как она работает, но выравнивание (слева, по центру, справа) не сортирует объект в выровненном порядке, например, строки / столбцы, определенные абсолютными границами.

Что касается событий для кнопок, текстовых ящиков ... Я должен быть в состоянии их программировать, у меня просто немного опыта с приложением Windows, в то время как в основном я выполняю консольные приложения.

Однако как мне добавить два графика в My Window? Я строю их в другом файле .py, используя matplotlib.pyplot, я загружаю часть данных из файлов .xls, используя pandas, а другая часть (вывод данных) будет получена через любой последовательный ( RS232 * 1018). *) или TCP / IP интерфейс. Я должен построить их в реальном времени, а также сохранить их (как .txt или .csv, это не имеет значения).

Не могли бы вы дать мне несколько советов по выбору правильной концепции «Моего окна», чтобы выполнить пример, который я привел ниже, и иметь возможность «легко» добавлять другие объекты в будущем, если это необходимо.

Я определенно думаю, что чем больше объектов в окне, тем лучше организация, потому что и метод iniUI(self) и класс Okno(QMainWindow) становятся довольно длинными.

Я сделал простая иллюстрация того, чего я пытаюсь достичь:

enter image description here

1 Ответ

1 голос
/ 31 марта 2020

Настройка выравнивания виджетов при добавлении их в макет не влияет на выравнивание виджетов, а только на их выравнивание в пределах пространства, которое макет предоставляет им. Кроме того, многие виджеты автоматически пытаются расширить себя (например, QLabels или представления элементов).

Например, QLabel имеет выравнивание текста по умолчанию влево / вертикально по центру, поэтому вам нужно установить that выравнивания, но он все равно будет пытаться расширить свое доступное пространство, если это позволят другие виджеты.

Чтобы получить то, что вам нужно, вы должны учитывать расстояние между виджетами, их sizePolicy (что представляет собой «Готовность» виджета к его размеру при использовании в макете, если он имеет фиксированный размер, может ли он увеличиваться / увеличиваться, может ли он уменьшаться и т. д. c).

Поскольку требуется некоторое пространство между столбцы, самое простое, что нужно сделать, это оставить пустые столбцы в макете и установить для этих столбцов коэффициент растяжения , используя setColumnStretch(), чтобы они пытались расширить как можно больше насколько это возможно.

Наконец, для сложных структур всегда лучше использовать вложенные макеты, что означает, что у вас будет установлен основной макет для виджета, а "child" la Вы добавляете его, так что каждый «раздел» имеет свой собственный менеджер макета, независимый от других. В следующем примере я реализовал такую ​​структуру:

    +-------------- main vertical layout ---------------+
    |                                                   |
    |  +------------ button grid layout -------------+  |
    |  |title|    |(empty)|      |(empty)|     |title|  |
    |  +-----+----+-------+------+-------+-----+-----+  |
    |  |label|edit|       |input |       |label|edit |  |
    |  +-----+----+-------+------+-------+-----+-----+  |
    |  |label|edit|       |input |       |label|edit |  |
    |  +-----+----+-------+------+-------+-----+-----+  |
    |  |label|edit|       |input |       |label|edit |  |
    |  +-----+----+-------+------+-------+-----+-----+  |
    +---------------------------------------------------+
    |                                                   |
    |  +---------- graph horizontal layout ----------+  |
    |  |                      |                      |  |
    |  |       left graph     |      right graph     |  |
    |  |                      |                      |  |
    |  +----------------------+----------------------+  |
    +---------------------------------------------------+
    |                                                   |
    |  +--------- button horizontal layout ----------+  |
    |  |        |                           |        |  |
    |  | button |         (stretch)         | button |  |
    |  |        |                           |        |  |
    |  +--------+---------------------------+--------+  |
    +---------------------------------------------------+ 

Вот как это выглядит:

screenshot of the layout

И это это код. Обратите внимание, что я удалил создание виджетов из init (если вы используете функцию initUi, не имеет большого смысла создавать их в другом месте).

from PyQt5 import QtWidgets, QtCore
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import sys


class Okno(QtWidgets.QMainWindow):
    def __init__(self):
        super(Okno, self).__init__()
        self.setGeometry(500, 500, 900, 500)
        self.setWindowTitle("My window")
        self.iniUI()

    def iniUI(self):
        w = QtWidgets.QWidget()
        self.setCentralWidget(w)

        mainLayout = QtWidgets.QVBoxLayout(w)

        grid = QtWidgets.QGridLayout()
        mainLayout.addLayout(grid)

        self.dataInputLabel = QtWidgets.QLabel('Data Input')
        grid.addWidget(self.dataInputLabel, 0, 0)
        self.dataInputLabel.setStyleSheet('color: red')

        portSettingLabel = QtWidgets.QLabel('Port setting', alignment=QtCore.Qt.AlignCenter)
        grid.addWidget(portSettingLabel, 0, 3)

        self.dataOutputLabel = QtWidgets.QLabel('Data Output', alignment=QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
        grid.addWidget(self.dataOutputLabel, 0, 6)
        self.dataOutputLabel.setStyleSheet('color: blue')

        # set the vertical policy to Maximum for labels, so they don't try to
        # expand themselves if there's more available space
        for label in (self.dataInputLabel, portSettingLabel, self.dataOutputLabel):
            label.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)

        grid.addWidget(QtWidgets.QLabel('Pressure [kPa]'), 1, 0)
        self.inputPressure = QtWidgets.QLineEdit(readOnly=True)
        grid.addWidget(self.inputPressure, 1, 1)

        grid.addWidget(QtWidgets.QLabel('Temperature [K]'), 2, 0)
        self.inputTemp = QtWidgets.QLineEdit(readOnly=True)
        grid.addWidget(self.inputTemp, 2, 1)

        grid.addWidget(QtWidgets.QLabel('Humidity [%]'), 3, 0)
        self.inputHumidity = QtWidgets.QLineEdit(readOnly=True)
        grid.addWidget(self.inputHumidity, 3, 1)

        self.portEdit = QtWidgets.QLineEdit(placeholderText='Enter port')
        grid.addWidget(self.portEdit, 1, 3)
        self.baudEdit = QtWidgets.QLineEdit(placeholderText='Baudrate')
        grid.addWidget(self.baudEdit, 2, 3)
        self.parityEdit = QtWidgets.QLineEdit(placeholderText='Parity')
        grid.addWidget(self.parityEdit, 3, 3)

        grid.addWidget(QtWidgets.QLabel('Pressure [kPa]'), 1, 5)
        self.outputPressure = QtWidgets.QLineEdit(readOnly=True)
        grid.addWidget(self.outputPressure, 1, 6)

        grid.addWidget(QtWidgets.QLabel('Temperature [K]'), 2, 5)
        self.outputTemp = QtWidgets.QLineEdit(readOnly=True)
        grid.addWidget(self.outputTemp, 2, 6)

        grid.addWidget(QtWidgets.QLabel('Humidity [%]'), 3, 5)
        self.outputHumidity = QtWidgets.QLineEdit(readOnly=True)
        grid.addWidget(self.outputHumidity, 3, 6)

        grid.setColumnStretch(2, 1)
        grid.setColumnStretch(4, 1)

        graphLayout = QtWidgets.QHBoxLayout()
        mainLayout.addLayout(graphLayout)
        # here insert your graphs...
        self.graphLeft = FigureCanvas(Figure())
        graphLayout.addWidget(self.graphLeft)
        self.graphRight = FigureCanvas(Figure())
        graphLayout.addWidget(self.graphRight)

        buttonLayout = QtWidgets.QHBoxLayout()
        mainLayout.addLayout(buttonLayout)

        self.openButton = QtWidgets.QPushButton('Open file')
        self.openButton.setMinimumWidth(150)
        self.openButton.clicked.connect(self.open_file)
        buttonLayout.addWidget(self.openButton)

        # add an empty "stretch", which acts as an expanding spacer on box layouts
        buttonLayout.addStretch()

        self.exitButton = QtWidgets.QPushButton('Exit')
        self.exitButton.clicked.connect(self.close)
        buttonLayout.addWidget(self.exitButton)

Наконец рассмотрите возможность использования Qt Designer, который полезен для создания сложных макетов (или, по крайней мере, визуализируйте их в процессе их проектирования, если вы все еще хотите делать все с помощью кода). Обратите внимание, что в этом случае вы должны следовать рекомендациям, предложенным для с использованием Designer (самое главное, никогда редактировать файлы python, созданные с помощью утилиты pyuic), или использовать loadUi('yourguifile.ui', self) (где self - это виджет / окно, которое вы хотите настроить с помощью пользовательского интерфейса) из модуля PyQt5.uic.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...