用于在长计算期间控制变量的简约图形界面

时间:2017-05-12 08:12:23

标签: python matlab pyqt5

我希望有一个简单的图形界面来控制Python中长计算中使用的变量。让我解释一下这个问题,并在MATLAB中展示一个我更了解的解决方案。我是python的初学者。

我有一个使用变量f的函数x

function f

x = 1;
for n = 1:10
  fprintf('%f\n', x)
  pause(1)
end

end

我希望能够在计算过程中使用图形界面更改x的值。在Matlab中,这可以相对简明地完成。我首先需要使x成为global变量,然后使用更新x的简单回调创建一个小部件。最终的代码是:

function computation_with_gui
% the main function simply creates the control and calls f.
    uicontrol('Style', 'slider', 'Min', 0, 'Max', 100, 'Position', [0 0 400 20], 'Callback', @callback)
    f();
end

function callback(h, d)
% the callback simply updates x
    global x
    x = h.Value;
end

function f
% function f now declares x as global
    global x
    x = 1;
    for n = 1:10
        fprintf('%f\n', x)
        pause(1)
    end
end

上面的脚本显示一个滑块(可能是另一个小部件,这里不重要)并启动计算。在计算过程中滑块不会冻结,我可以使用它来控制x显示的f的值。最后,程序在f完成时停止。总的来说,将这个简单的图形界面添加到f所需的代码实际上是最小的。

我的问题是,如何在Python中做类似的事情?在本案中,我显然赞成简明扼要。我倾向于使用PyQt5(仅仅因为它配备了我的配置),但是如果另一个框架能够实现更简洁的东西,那也没关系。同样,如果使事情变得更容易,那么小部件将不是滑块。

1 个答案:

答案 0 :(得分:0)

您可以执行与MATLAB中非常相似的操作。我将调整PyQt slider example中的TutorialsPoint来演示:

import sys, threading, time
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QLabel, QSlider, QVBoxLayout, QWidget

x = 1

class GUI(QWidget):
    def __init__(self, parent = None):
        super().__init__(parent)

        self.slider = QSlider(Qt.Horizontal)
        self.slider.setMinimum(0)
        self.slider.setMaximum(100)
        self.slider.setValue(x)
        self.slider.setTickPosition(QSlider.TicksBelow)
        self.slider.setTickInterval(5)

        layout = QVBoxLayout()
        layout.addWidget(self.slider)

        self.setLayout(layout)
        self.slider.valueChanged.connect(self.valuechange)

    def valuechange(self):
        global x
        x = self.slider.value()

def process(gui):
    for n in range(10):
        print(x)
        time.sleep(1)
    gui.close()

def main():
    app = QApplication(sys.argv)
    gui = GUI()
    gui.show()
    threading.Thread(target=process, args=(gui,)).start()
    sys.exit(app.exec())

if __name__ == '__main__':
    main()

如您所见,这里有一些差异。首先,任务必须在后台线程中启动,因为主线程将被app.exec阻止。另一方面,处理函数需要有一种让GUI知道它已完成的方法,我通过传入对GUI窗口的引用来实现。

虽然使用全局变量通常是一个坏主意,但我在这里使用它作为MATLAB代码的直接翻译。