我正在开发一个用于管理虚拟环境的小型 GUI。在主窗口中,我想要显示来自默认目录的现有虚拟环境并以表格视图呈现。到目前为止,这个功能已经实现了。
现在我注意到,如果我选择其他默认目录,我必须关闭 GUI 然后再次打开才能看到内容。不幸的是,在我的计划中没有考虑到这一点(我在 Python 中还有些经验不足)。
我想要添加一个按钮,通过该按钮可以更新表格视图的内容。同时,在 settings.py 中的现有按钮 `okButton`(它会确认所选标准目录的输入)也应该更新表格视图。
我尝试使用 `pyqtsignal()` 和 `pyqtslot()`,但我不知道如何将其应用到我的代码中。表格视图的数据(例如版本、路径等)来自于 organize.py 中的循环。项目被收集到列表中,然后在表格中显示。
我该如何在点击按钮时刷新视图?我需要修改代码结构吗?
以下是代码的最小可重现部分:
如果您想要查看,您也可以在此处查看存储库。其中没有商业背景。
现在我注意到,如果我选择其他默认目录,我必须关闭 GUI 然后再次打开才能看到内容。不幸的是,在我的计划中没有考虑到这一点(我在 Python 中还有些经验不足)。
我想要添加一个按钮,通过该按钮可以更新表格视图的内容。同时,在 settings.py 中的现有按钮 `okButton`(它会确认所选标准目录的输入)也应该更新表格视图。
我尝试使用 `pyqtsignal()` 和 `pyqtslot()`,但我不知道如何将其应用到我的代码中。表格视图的数据(例如版本、路径等)来自于 organize.py 中的循环。项目被收集到列表中,然后在表格中显示。
我该如何在点击按钮时刷新视图?我需要修改代码结构吗?
以下是代码的最小可重现部分:
如果您想要查看,您也可以在此处查看存储库。其中没有商业背景。
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import organize
import settings
class Ui_MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setupUi()
def setupUi(self):
self.selectDefaultDir = settings.SetDefaultDirectory()
self.setWindowTitle("MainWindow")
self.setGeometry(430, 335, 750, 330)
centralwidget = QWidget(self)
self.v_Layout_1 = QVBoxLayout()
self.v_Layout_2 = QVBoxLayout(centralwidget)
selectButton = QPushButton(
"Set default dir", clicked=self.selectButton_clicked
)
# venv table
venvTable = QTableView(centralwidget)
venvTable.verticalHeader().setVisible(False)
venvTable.setSelectionBehavior(QAbstractItemView.SelectRows)
venvTable.setEditTriggers(QAbstractItemView.NoEditTriggers)
venvTable.setAlternatingRowColors(True)
# adjust vertical headers
v_HeaderTV2 = venvTable.verticalHeader()
v_HeaderTV2.setVisible(False)
v_HeaderTV2.setDefaultSectionSize(27.5)
# adjust (horizontal) headers
h_HeaderTV2 = venvTable.horizontalHeader()
h_HeaderTV2.setDefaultAlignment(Qt.AlignLeft)
h_HeaderTV2.setDefaultSectionSize(180)
h_HeaderTV2.setStretchLastSection(True)
# set table view model
self.modelTV2 = QStandardItemModel(centralwidget)
self.modelTV2.setColumnCount(3)
self.modelTV2.setHorizontalHeaderLabels(
["Venv Name", "Version", "Path"]
)
venvTable.setModel(self.modelTV2)
self.v_Layout_1.addWidget(venvTable)
self.v_Layout_1.addWidget(selectButton)
self.v_Layout_2.addLayout(self.v_Layout_1)
self.setCentralWidget(centralwidget)
def popVenvTable(self):
"""
Populate the venv table view.
"""
for i in range(len(organize.venvDirs)):
self.modelTV2.insertRow(0)
self.modelTV2.setItem(0, 0, QStandardItem(organize.venvDirs[i]))
self.modelTV2.setItem(0, 1, QStandardItem(organize.venvVers[i]))
self.modelTV2.setItem(0, 2, QStandardItem(organize.venvPath[i]))
def selectButton_clicked(self):
self.selectDefaultDir.exec_()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
ui = Ui_MainWindow()
ui.popVenvTable()
ui.show()
sys.exit(app.exec_())
organize.py
# -*- coding: utf-8 -*-
from subprocess import Popen, PIPE
import os
#]===========================================================================[#
#] GET VENVS FROM DEFAULT DIRECTORY [#=======================================[#
#]===========================================================================[#
venvDirs, venvVers, venvPath = [], [], []
def getVenvs():
"""
Get the sub directories (venv directories) from the default directory.
"""
# get the path (str) to the default dir from file
with open("def/default", 'r') as default:
defDir = default.read()
default.close()
# get all folders inside the selected default dir
subDirs = os.listdir(defDir)
# loop over the subdirs of the selected default dir
for i, _dir in enumerate(subDirs):
# if there's a 'bin' folder within the subdir, and if it contains a
# file named 'python', then try to get the version
if ("bin" in os.listdir('/'.join([defDir, _dir]))
and "python" in os.listdir('/'.join([defDir, _dir, "bin"]))):
try:
getVers = Popen(
['/'.join([defDir, _dir, "bin", "python"]), "-V"],
stdout=PIPE, universal_newlines=True
)
venvVersion = getVers.communicate()[0].strip()
except Exception as err:
# in case there's a file named 'python' but
# isn't a python executable
print(
err.args[1]+':',
"[list index:", str(i)+']',
'/'.join([defDir, _dir, "bin"])
)
continue
venvDirs.append(_dir)
venvVers.append(venvVersion)
venvPath.append(defDir)
getVenvs()
if __name__ == "__main__":
for i in range(len(venvDirs)):
print(venvDirs[i])
print(venvVers[i])
print(venvPath[i])
settings.py
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class SetDefaultDirectory(QDialog):
"""
Set the default directory, where to look for virtual environments.
"""
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
#]===================================================================[#
#] WINDOW SETTINGS [#================================================[#
#]===================================================================[#
self.setWindowTitle("Set Default Directory")
self.setGeometry(600, 365, 500, 100)
self.setFixedSize(500, 100)
v_Layout = QVBoxLayout(self)
h_Layout = QHBoxLayout()
gridLayout = QGridLayout()
defaultDirLabel = QLabel("Default Venv Directory:")
self.defaultDirLineEdit = QLineEdit()
defaultDirLabel.setBuddy(self.defaultDirLineEdit)
folder_icon = QIcon.fromTheme("folder")
selectDirToolButton = QToolButton(
toolTip="Browse",
clicked=self.selectDirTButton_clicked
)
selectDirToolButton.setFixedSize(26, 27)
selectDirToolButton.setIcon(folder_icon)
horizontalLine = QFrame()
horizontalLine.setFrameShape(QFrame.HLine)
horizontalLine.setFrameShadow(QFrame.Sunken)
cancelButton = QPushButton(
"Cancel", clicked=self.close
)
okButton = QPushButton(
"OK", clicked=self.okButton_clicked
)
spacerItem = QSpacerItem(
40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum
)
gridLayout.addWidget(defaultDirLabel, 0, 0, 1, 1)
gridLayout.addWidget(self.defaultDirLineEdit, 0, 1, 1, 1)
gridLayout.addWidget(selectDirToolButton, 0, 2, 1, 1)
h_Layout.addItem(spacerItem)
h_Layout.addWidget(okButton, 0, Qt.AlignBottom)
h_Layout.addWidget(cancelButton, 0, Qt.AlignBottom)
v_Layout.addLayout(gridLayout)
v_Layout.addWidget(horizontalLine)
v_Layout.addLayout(h_Layout)
def selectDirTButton_clicked(self):
"""
Select directory which should be set as default.
"""
fileDiag = QFileDialog()
directory = fileDiag.getExistingDirectory()
self.defaultDirLineEdit.setText(directory)
def okButton_clicked(self):
"""
Store the absolute path (as str) to the selected dir in 'def/default'.
"""
with open("def/default", 'w') as default:
default.write(self.defaultDirLineEdit.text())
default.close()
self.close()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
settingsUI = SetDefaultDirectory()
settingsUI.show()
sys.exit(app.exec_())