欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

利用Python3开发一款小工具 (界面背后的代码)

程序员文章站 2022-07-12 11:19:06
...

界面设计参照上一篇博客(https://blog.csdn.net/hitguolu/article/details/82620681),

前文已经写到,只有界面没有后台的程序,界面是没有用的。本篇将对界面背后的代码进行介绍,辛辛苦苦在后面执行,今天终于露脸了,话不多说,我们开始了。

前文讲到,用pyUIC可以将ui界面转换成py文件,py文件中其实就是生成一个类,类名为UI_MainWindows,该类包含两个方法,setupUi和retranslateUi。一般来说,我们不会直接用这个类的,在这里我们会新定义一个类,这个类我们会参照UI_MainWindowsd类。

class UI_AutoCodeCheck(QtWidgets.QMainWindows):
    logSignal = QtCore.pyqtSignal(str)

    def __init__(self):
    ...

    def retranslateUi(self):
    ...

1、界面中的控件

下图就是我们用的所有控件,
利用Python3开发一款小工具 (界面背后的代码)
包括了GroupBox、PushButton、Label、LineEdit、ComboBox、Checkbox、TextBrowser、PlainTextEdit等。

  • LineEdit
    我们常用来做参数的输入
  • GroupBox
    就是个面板,控件常常用于逻辑地组合一组控件,如RadioButton 及 CheckBox控件,显示一个框架,其上有一个标题
  • PushBotton
    可以理解为一个按钮
  • ComboBox
    是下拉框控件
  • CheckBox
    多选框控件,要结合GroupBox使用
  • TextBrowser是文字显示
  • PlainTextEdit
    是可以编辑的文本

2、如何给一个控件添加事件响应

我们分别给控件添加事件响应

-LineEdit
想想,我们在界面输入的文字是怎么传递到程序中的呢?排除法,肯定不是自己跑进去的。在pyqt中,我们需要这样做:
1)给控件添加connect函数

self.LinuxServerIP.textChanged.connect(self.configureEdited)

从该语句其实就可以知道,只要LinuxServerIP这个输入框发生了变化,就会触发执行configureEdited函数,要想保存该参数,就要在connect函数中添加处理代码
2)connect函数中读取界面中的内容

serverIp = self.LinuxServerIP.text()

该语句就是用来获取LineEdit中的字符的,需要注意的时,如果我们输入的是数字,需要讲字符串转换成我们需要的格式。
不过,我们通常不会再connect函数中直接保存,因为你在输入的第一个字符开始,每输入一个字符,都会进入connect函数中,这个不是我们想要的。
因此我在这里的处理,通常用这个configureEdited函数校验参数是否已经满足运行的要求,然后控制START按钮是否允许被用户点击。这个在后面界面的约束进行介绍。

– 浏览按钮的实现

self.BrowseFileButton.clicked.connect(self.fileBrowsePressed)
def fileBrowsePressed(self):
    self.dirSelector = QtWidgets.QFileDialog()
    self.dirSelector.setGeometry(QtCore.QRect(20, 0, 651, 441))
    browsedir = (os.getcwd() if self.LocalRepoDir.text() == '' else self
                 .LocalRepoDir.text())
    dir = self.dirSelector.getExistingDirectory(
        self.centralwidget, "Select Directory", browsedir,
        QtWidgets.QFileDialog.ShowDirsOnly |
        QtWidgets.QFileDialog.DontResolveSymlinks)

    self.LocalRepoDir.setText(browsedir if dir == '' else dir)

– comboBox

self.StationTypeComboBox.currentIndexChanged.connect(self.stationTypeComboBoxChange)

这段代码用于感知下拉框状态的改变,如果想知道下拉框选择的选项,可以使用两种,

#此函数可以获取当前选择的下拉框中的字符串
self.StationTypeComboBox.currentText() 

#此函数可以获取当前下拉框的索引,如0,1,2,3
self.StationTypeComboBox.currentIndex()

– checkBox
在我们的界面中,有一组多选框,多选框状态的获取可以使用如下方法:

self.LinuxCompileReleaseBin.stateChanged.connect(self.LinuxCompileReleaseBinSwitchChanged)

判断当前状态是否是选中状态

def LinuxCompileReleaseBinSwitchChanged(self, state)
    if state == QtCore.Qt.Checked:
        pass

如果想让程序选中或者取消选中复选框,则可以

self.LinuxCompileReleaseBin.setCheckState(QtCore.Qt.Unchecked)#取消选中
self.LinuxCompileReleaseBin.setCheckState(QtCore.Qt.Checked)#选中

– 鼠标响应事件
之所以要有这个事件,是因为我希望实现一个功能,就是在RunningLogs窗口双击鼠标,可以弹出一个messageBox,然后选择是否要跳转到详细日志保存目录及版本包存放目录。因此,我给重写了TextBrowser类。

class MyTextBrowser(QtWidgets.QTextBrowser):
    def __init__(self, parent=None):
        super(MyTextBrowser, self).__init__(parent)
    # 双击鼠标事件响应
    def mouseDoubleClickEvent(self, event):
        msg = QtWidgets.QMessageBox.information(self,
                            "Rungging logs",
                            "是否查看详细日志\n",
                            QtWidgets.QMessageBox.Yes|QtWidgets.QMessageBox.NO,
                            QtWidgets.QMessageBox.Yes)

        if QtWidgets.QMessageBox.Yes == msg:
            start_directory = os.getcwd()
            cmd = "explorer.exe " + start_directory
            try:
                run(cmd, shell = True)    
                # 调用了subprocesss的run函数,执行explorer打开本地目录
            except Exception as err:
                print(err)
                ... #后续异常处理

于是,在定义TextBrowser时,就用了MyTextBrower类定义,这就赋予了RunningLogs控件有了鼠标双击事件响应

self.textBrowser = MyTextBrowser(self.RunningLogs)

3、界面的约束

根据我们的需求,对界面提出了一下两点约束:
1、用户配置信息不完善时,不允许‘START’按钮被按下,而且多选框按钮必须选择一个才能允许点击’START’按钮
2、站型切换时,要把所有的checkBox设置为未选中状态

  • 约束1的实现
    需求:Linux服务器地址2个、远程目录、本地目录、用户名、密码必须全都要配置
    首先给LinuxServerIP1、remoteDir、LocalReportDir、username、password、LinuxServerIP2加上connect函数,改变这些值,就会触发我们的校验函数
self.LinuxServerIP1.textChanged.connect(self.configureEdited)
self.LinuxServerIP2.textChanged.connect(self.configureEdited)
self.LinuxRemoteDir.textChanged.connect(self.configureEdited)
self.LocalRepoDir.textChanged.connect(self.configureEdited)
self.PassWord.textChanged.connect(self.configureEdited)
self.UserName.textChanged.connect(self.configureEdited)
def configureEdited(self):
    LinuxServerIP1 = self.LinuxServerIP1.text()
    RemoteDir = self.LinuxRemoteDir.text()
    LocalRepoDir = self.LocalRepoDir.text()
    username = self.UserName.text()
    password = self.PassWord.text()
    LinuxServerIP2= self.LinuxServerIP2.text() 
    #变量名做了模糊处理,正常编码时,尽量避免这种命名方法

    if (LinuxServerIP1 != '' and RemoteDir != '' and 
        LocalRepoDir != '' and username != '' and
        password != '' and LinuxServerIP2 != ''):
        # ischeckSettingComplete函数是用来判断checkbox是否至少有一个被选中的
        if self.isCheckSettingComplete() == False:
            self.StartButton.setEnabled(False)
        else:
            self.StartButton.setEnabled(True)
  • 约束2的实现
    需求:站型在A和B之间切换时,要清空所有的脚本执行多选框
    1、首先给ComboBox加入connect函数
self.StationTypeComboBox.currentIndexChanged.connect(self.stationTypeComboBoxChange)

2、编写connect函数

def stationTypeComboBoxChange(self):
    self.LinuxCompileReleaseBin.setCheckState(QtCore.Qt.Unchecked)#取消选中
    self.LinuxCompileDebugBin.setCheckState(QtCore.Qt.Unchecked)
    self.LinuxCompileX86DebugBin.setCheckState(QtCore.Qt.Unchecked)
    self.LinuxFtBin.setCheckState(QtCore.Qt.Unchecked)

4、信号量的用处

这里简单介绍一下,后面会专门对信号量进行讲解。
我们在这里,使用了信号量用于日志的输出,信号量的定义如下

logSignal = QtCore.pyqtSignal(str)
# 这个str就是我们需要打印出的日志

以上只是信号量的定义,如何将信号量和写日志联系起来,可以想一想。
其实,我们还是用的connect函数。

self.logSignal.connect(self.LogParsingShow)

我们只需要定义一下logParsingShow函数即可

def logParsingShow(self, log_info):
    # 插入了日志的时间
    self.textBrowser.insertPlainText(str(dateTime.datetime.now().strftime('%H:%M:%S')))
    self.textBrowser.insetPlainText(' ')
    self.textBrowser.insetPlainText(log_info)

    # 实现进度条的自动滚动,能够保证看到的是最新的日志
    self.textBrowser.moveCursor(QtGui.QTextCursor.End) 

使用的时候

self.logSignal.emit("Connected to server 192.168.53.238\n")

这样,日志就输出到了textBrower上。
效果就是这样:

10:25:03 Connected to server 192.168.53.238
10:25:04 upload modified files completely
10:25:05 Exec rrc_bin_x86_release_debug.sh success
....