class App(QDialog): def __init__(self): app = QApplication(sys.argv) super().__init__() self.setWindowTitle('PyQt6 Grid Layout') self.setGeometry(100, 100, 320, 100) self.CreateGridLayout() self.windowLayout = QVBoxLayout() self.windowLayout.addWidget(self.horizontalGroupBox) self.setLayout(self.windowLayout) self.show() sys.exit(app.exec()) def CreateGridLayout(self): self.horizontalGroupBox = QGroupBox("Grid") self.layout = QGridLayout() self.layout.setColumnStretch(2, 4) self.layout.setColumnStretch(1, 4) for label in "123456789": self.MakeButton(label) self.horizontalGroupBox.setLayout(self.layout) def MakeButton(self, label): button = QPushButton(label) button.clicked.connect(lambda: self.on_click(button)) self.layout.addWidget(button) def on_click(self, pushButton): print('PyQt5 {0} button clicked.'.format(pushButton.text()))
def setUpMainWindow(self): """Set up the GUI's main window.""" search_line_edit = QLineEdit() search_line_edit.setPlaceholderText( "Enter text to search for a word below") list_of_words = self.loadWordsFromFile() list_view = QListView() # Create a model instance and pass the list of words to the model model = ListModel(list_view, list_of_words) list_view.setModel(model) # Create QCompleter object that shares the same model as the QListView completer = QCompleter(list_of_words) completer.setFilterMode(Qt.MatchFlag.MatchStartsWith) completer.setModel(model) search_line_edit.setCompleter( completer) # Set the completer for the QLineEdit # Create a layout and organize all of the objects # into a QGroupBox main_v_box = QVBoxLayout() main_v_box.addWidget(search_line_edit) main_v_box.addWidget(list_view) word_group_box = QGroupBox("Keywords") word_group_box.setLayout(main_v_box) self.setCentralWidget(word_group_box)
def __init__(self, parent, directory, is_checked): """Simple modal Preferences dialog""" super().__init__(parent) self.setWindowTitle("Preferences") self.setModal(True) image_dir_label = QLabel( f"<b>Images Location:</b> {directory.absolutePath()}") self.delete_images_checkbox = QCheckBox("Delete Original Images") self.delete_images_checkbox.setToolTip( """<p>If checked, images that are copied to the <b>Images Location</b> are also deleted from their original location.</p>""" ) self.delete_images_checkbox.setChecked(is_checked) handling_v_box = QVBoxLayout() handling_v_box.addWidget(self.delete_images_checkbox) handling_group_box = QGroupBox("Image Handling:") handling_group_box.setLayout(handling_v_box) self.button_box = QDialogButtonBox( QDialogButtonBox.StandardButton.Save | QDialogButtonBox.StandardButton.Cancel) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) # Add a layout to the dialog box dialog_v_box = QVBoxLayout() dialog_v_box.addWidget(image_dir_label) dialog_v_box.addWidget(handling_group_box) dialog_v_box.addStretch(1) dialog_v_box.addWidget(self.button_box) self.setLayout(dialog_v_box)
class App(QDialog): def __init__(self): app = QApplication(sys.argv) super().__init__() self.setWindowTitle('PyQt6 Horizontal Layout') self.setGeometry(100, 100, 400, 100) self.CreateHorizontalLayout() windowLayout = QVBoxLayout() windowLayout.addWidget(self.horizontalGroupBox) self.setLayout(windowLayout) self.show() sys.exit(app.exec()) def CreateHorizontalLayout(self): self.horizontalGroupBox = QGroupBox("What is your favorite color?") layout = QHBoxLayout() buttonBlue = QPushButton('Blue', self) buttonBlue.clicked.connect(lambda: self.on_click(buttonBlue)) layout.addWidget(buttonBlue) buttonRed = QPushButton('Red', self) buttonRed.clicked.connect(lambda: self.on_click(buttonRed)) layout.addWidget(buttonRed) buttonGreen = QPushButton('Green', self) buttonGreen.clicked.connect(lambda: self.on_click(buttonGreen)) layout.addWidget(buttonGreen) self.horizontalGroupBox.setLayout(layout) def on_click(self, pushButton): print('PyQt6 {0} button clicked.'.format(pushButton.text()))
class Window(QDialog): def __init__(self): super(Window, self).__init__() self.groupBox = QGroupBox("What is your favorite sport ?") self.radiobtn3 = QRadioButton("BasketBall") self.radiobtn3.setIcon(QIcon("")) self.radiobtn2 = QRadioButton("Swimming") self.radiobtn2.setIcon(QIcon("")) self.radiobtn1 = QRadioButton("FootBall") self.radiobtn1.setIcon(QIcon("")) self.label = QLabel("You Have Selected FootBall") self.title = " " self.left = 100 self.top = 200 self.width = 400 self.height = 300 self.InitWindow() def InitWindow(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.radioButton() vbox = QVBoxLayout() vbox.addWidget(self.groupBox) vbox.addWidget(self.label) self.setLayout(vbox) self.show() def radioButton(self): hbox = QHBoxLayout() self.radiobtn1.setChecked(True) self.radiobtn1.toggled.connect(self.OnRadioButton) hbox.addWidget(self.radiobtn1) self.radiobtn2.setChecked(False) self.radiobtn2.toggled.connect(self.OnRadioButton) hbox.addWidget(self.radiobtn2) self.radiobtn3.setChecked(False) self.radiobtn2.toggled.connect(self.OnRadioButton) hbox.addWidget(self.radiobtn3) self.groupBox.setLayout(hbox) def OnRadioButton(self): # Which radioBtn send message radioBtn = self.sender() if radioBtn.isChecked(): self.label.setText("You Have Selected " + radioBtn.text())
def show_setting(self, conf: dict, layout: QGridLayout): groups = list() x = 0 y = 0 shape = 3 for key in conf.keys(): if type(conf[key]) == bool or type(conf[key]) == str: continue conf_title = conf[key]["title"] conf_enabled = conf[key]["enabled"] conf_times = conf[key]["times"] group = QGroupBox(conf_title) group.setStyleSheet("QGroupBox{border-radius:5px;}") group.setToolTip(conf_title + " 的设置") enabled = QCheckBox("启用") enabled.setObjectName(key) enabled.setToolTip("单击切换开关状态") enabled.setChecked(conf_enabled) enabled.setStyleSheet( "QCheckBox::indicator{width:10px;height:10px;border:none;border-radius:5px;background:#9BE3DE;}QCheckBox::indicator:unchecked{background:#BEEBE9;}QCheckBox::indicator:unchecked:hover{background:#9AD3BC;}QCheckBox::indicator:checked{background:#95E1D3;}QCheckBox::indicator:checked:hover{background:#98DED9;}" ) times = QHBoxLayout() times_label = QLabel("次数:") times_label.setStyleSheet( "QLabel{background:transparent;border:none;border-radius:5px;}" ) times_input = EnhancedEdit() times_input.setObjectName(key) times_input.setText(str(conf_times)) times_input.setToolTip("仅限正整数") times_input.setValidator( QRegularExpressionValidator( QRegularExpression("^[1-9][0-9]{1,8}$"))) times_input.setStyleSheet( "QLineEdit{border:1px solid #F3EAC2;border-radius:5px;background:transparent;}QLineEdit:hover{border:1px solid #F5B461;}" ) times.addWidget(times_label) times.addWidget(times_input) group_layout = QVBoxLayout() group_layout.addWidget(enabled) group_layout.addLayout(times) group.setLayout(group_layout) group.setObjectName(key) groups.append(group) for group in groups: if y >= shape: x = x + 1 y = 0 layout.addWidget(group, x, y) y = y + 1 self.logger.debug("最后的元素位置:(%d,%d)" % (x, y)) return (x, y)
class Window(QDialog): def __init__(self): super().__init__() self.title = "PyQt6 Window" self.top = 100 self.left = 100 self.width = 400 self.height = 300 self.InitWindow() def InitWindow(self): self.setWindowIcon(QtGui.QIcon("home.png")) self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.createLayout() vbox = QVBoxLayout() vbox.addWidget(self.groupBox) self.setLayout(vbox) self.show() def createLayout(self): self.groupBox = QGroupBox("What Is Your Favorite Sport?") hboxlayout = QHBoxLayout() self.button = QPushButton("Football", self) self.button.setIcon(QtGui.QIcon("home.png")) self.button.setIconSize(QSize(40, 40)) self.button.setToolTip("This Is Click Me Button") self.button.setMinimumHeight(40) hboxlayout.addWidget(self.button) self.button1 = QPushButton("Cricket", self) self.button1.setIcon(QtGui.QIcon("home.png")) self.button1.setIconSize(QSize(40, 40)) self.button1.setMinimumHeight(40) self.button1.setToolTip("This Is Click Me Button") hboxlayout.addWidget(self.button1) self.button2 = QPushButton("Tennis", self) self.button2.setIcon(QtGui.QIcon("home.png")) self.button2.setIconSize(QSize(40, 40)) self.button2.setMinimumHeight(40) self.button2.setToolTip("This Is Click Me Button") hboxlayout.addWidget(self.button2) self.groupBox.setLayout(hboxlayout)
def __init__(self, parent, selected_image): """Modeless dialog that displays file information for images""" super().__init__(parent) metadata = self.collectImageMetaData(selected_image) self.setWindowTitle(f"{metadata['file_name']} Info") # Create widgets for displaying information image_label = QLabel(f"<b>{metadata['base_name']}</b>") date_created = QLabel( f"Created: {metadata['date_created'].toString('MMMM d, yyyy h:mm:ss ap')}" ) image_type = QLabel(f"Type: {metadata['extension']}") image_size = QLabel(f"Size: {metadata['size']:,} bytes") image_location = QLabel(f"Location: {metadata['file_path']}") date_modified = QLabel( f"""Modified: {metadata['last_modified'].toString('MMMM d, yyyy h:mm:ss ap')}""" ) # Organize widgets that display metadata using containers/layouts general_v_box = QVBoxLayout() general_v_box.addWidget(image_type) general_v_box.addWidget(image_size) general_v_box.addWidget(image_location) general_group_box = QGroupBox("General:") general_group_box.setLayout(general_v_box) extra_v_box = QVBoxLayout() extra_v_box.addWidget(date_modified) extra_group_box = QGroupBox("Extra Info:") extra_group_box.setLayout(extra_v_box) self.button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok) self.button_box.accepted.connect(self.accept) # Add a layout to the dialog box dialog_v_box = QVBoxLayout() dialog_v_box.addWidget(image_label) dialog_v_box.addWidget(date_created) dialog_v_box.addWidget(general_group_box) dialog_v_box.addWidget(extra_group_box) dialog_v_box.addStretch(1) dialog_v_box.addWidget(self.button_box) self.setLayout(dialog_v_box)
class Window(QDialog): def __init__(self): super().__init__() self.title = "PyQt6 Window" self.top = 100 self.left = 100 self.width = 400 self.height = 300 self.InitWindow() def InitWindow(self): self.setWindowIcon(QtGui.QIcon("home.png")) self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.createLayout() vbox = QVBoxLayout() vbox.addWidget(self.groupBox) self.setLayout(vbox) self.show() def createLayout(self): self.groupBox = QGroupBox( "What is your favorite programming language?") gridLayout = QGridLayout() button1 = QPushButton("Python", self) gridLayout.addWidget(button1, 0, 0) button2 = QPushButton("C++", self) gridLayout.addWidget(button2, 0, 1) button3 = QPushButton("Java", self) gridLayout.addWidget(button3, 1, 0) button4 = QPushButton("C#", self) gridLayout.addWidget(button4, 1, 1) self.groupBox.setLayout(gridLayout)
def __init__( self, parent: Optional[QWidget] = None, *args: Tuple[Any, Any], **kwargs: Tuple[Any, Any], ) -> None: """ Grouped controls box for generating mazes """ super(GenerateMazeGroupView, self).__init__(parent=parent, *args, **kwargs) self.setContentsMargins(0, 0, 0, 0) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) groupbox = QGroupBox("Generate Maze") layout.addWidget(groupbox) vbox = QFormLayout() groupbox.setLayout(vbox) self.__mazeSizePicker = XYPicker( minimum=XY(2, 2), maximum=XY(250, 250), initialValue=XY(2, 2), parent=self, ) self.__simplyConnectedCheckbox = QCheckBox() self.__simplyConnectedCheckbox.setChecked(True) generateButton = QPushButton("Generate") generateButton.clicked.connect( self.__onGenerateButtonPressed) # type: ignore vbox.addRow("Size", self.__mazeSizePicker) vbox.addRow("Simply Connected", self.__simplyConnectedCheckbox) vbox.addRow(generateButton) self.setLayout(layout)
class Window(QDialog): def __init__(self): super(Window, self).__init__() self.groupBox = QGroupBox( "What is your favorite programming Language ?") self.groupBox.setFont(QFont("Sanserif", 13)) self.lineEdit = QLineEdit() self.label = QLabel("You input string is :") self.title = " " self.left = 100 self.top = 200 self.width = 400 self.height = 300 self.InitWindow() def InitWindow(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.createLineEdit() vbox = QVBoxLayout() vbox.addWidget(self.groupBox) vbox.addWidget(self.label) self.setLayout(vbox) self.show() def createLineEdit(self): hboxLayout = QHBoxLayout() self.lineEdit.returnPressed.connect(self.onReturn_pressed) hboxLayout.addWidget(self.lineEdit) self.groupBox.setLayout(hboxLayout) def onReturn_pressed(self): self.label.setText(self.lineEdit.text())
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.setupTrayicon() self.setupVariables() self.setupUi() self.setupConnections() self.show() def setupVariables(self): settings = QSettings() self.workEndTime = QTime( int(settings.value(workHoursKey, 0)), int(settings.value(workMinutesKey, 25)), int(settings.value(workSecondsKey, 0)), ) self.restEndTime = QTime( int(settings.value(restHoursKey, 0)), int(settings.value(restMinutesKey, 5)), int(settings.value(restSecondsKey, 0)), ) self.timeFormat = "hh:mm:ss" self.time = QTime(0, 0, 0, 0) self.workTime = QTime(0, 0, 0, 0) self.restTime = QTime(0, 0, 0, 0) self.totalTime = QTime(0, 0, 0, 0) self.currentMode = Mode.work self.maxRepetitions = -1 self.currentRepetitions = 0 def setupConnections(self): """ Create button connections """ self.startButton.clicked.connect(self.startTimer) self.startButton.clicked.connect( lambda: self.startButton.setDisabled(True)) self.startButton.clicked.connect( lambda: self.pauseButton.setDisabled(False)) self.startButton.clicked.connect( lambda: self.resetButton.setDisabled(False)) self.pauseButton.clicked.connect(self.pauseTimer) self.pauseButton.clicked.connect( lambda: self.startButton.setDisabled(False)) self.pauseButton.clicked.connect( lambda: self.pauseButton.setDisabled(True)) self.pauseButton.clicked.connect( lambda: self.resetButton.setDisabled(False)) self.pauseButton.clicked.connect( lambda: self.startButton.setText("continue")) self.resetButton.clicked.connect(self.resetTimer) self.resetButton.clicked.connect( lambda: self.startButton.setDisabled(False)) self.resetButton.clicked.connect( lambda: self.pauseButton.setDisabled(True)) self.resetButton.clicked.connect( lambda: self.resetButton.setDisabled(True)) self.resetButton.clicked.connect( lambda: self.startButton.setText("start")) self.acceptTaskButton.pressed.connect(self.insertTask) self.deleteTaskButton.pressed.connect(self.deleteTask) """ Create spinbox connections """ self.workHoursSpinBox.valueChanged.connect(self.updateWorkEndTime) self.workMinutesSpinBox.valueChanged.connect(self.updateWorkEndTime) self.workSecondsSpinBox.valueChanged.connect(self.updateWorkEndTime) self.restHoursSpinBox.valueChanged.connect(self.updateRestEndTime) self.restMinutesSpinBox.valueChanged.connect(self.updateRestEndTime) self.restSecondsSpinBox.valueChanged.connect(self.updateRestEndTime) self.repetitionsSpinBox.valueChanged.connect(self.updateMaxRepetitions) """ Create combobox connections """ self.modeComboBox.currentTextChanged.connect(self.updateCurrentMode) """ Create tablewidget connections """ self.tasksTableWidget.cellDoubleClicked.connect( self.markTaskAsFinished) def setupUi(self): self.size_policy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) """ Create tabwidget """ self.tabWidget = QTabWidget() """ Create tab widgets """ timerWidget = self.setupTimerTab() tasksWidget = self.setupTasksTab() statisticsWidget = self.setupStatisticsTab() """ add tab widgets to tabwidget""" self.timerTab = self.tabWidget.addTab(timerWidget, makeIcon("timer"), "Timer") self.tasksTab = self.tabWidget.addTab(tasksWidget, makeIcon("tasks"), "Tasks") self.statisticsTab = self.tabWidget.addTab(statisticsWidget, makeIcon("statistics"), "Statistics") """ Set mainwindows central widget """ self.setCentralWidget(self.tabWidget) def setupTimerTab(self): settings = QSettings() self.timerContainer = QWidget(self) self.timerContainerLayout = QVBoxLayout(self.timerContainer) self.timerContainer.setLayout(self.timerContainerLayout) """ Create work groupbox""" self.workGroupBox = QGroupBox("Work") self.workGroupBoxLayout = QHBoxLayout(self.workGroupBox) self.workGroupBox.setLayout(self.workGroupBoxLayout) self.workHoursSpinBox = QSpinBox( minimum=0, maximum=24, value=int(settings.value(workHoursKey, 0)), suffix="h", sizePolicy=self.size_policy, ) self.workMinutesSpinBox = QSpinBox( minimum=0, maximum=60, value=int(settings.value(workMinutesKey, 25)), suffix="m", sizePolicy=self.size_policy, ) self.workSecondsSpinBox = QSpinBox( minimum=0, maximum=60, value=int(settings.value(workSecondsKey, 0)), suffix="s", sizePolicy=self.size_policy, ) """ Create rest groupbox""" self.restGroupBox = QGroupBox("Rest") self.restGroupBoxLayout = QHBoxLayout(self.restGroupBox) self.restGroupBox.setLayout(self.restGroupBoxLayout) self.restHoursSpinBox = QSpinBox( minimum=0, maximum=24, value=int(settings.value(restHoursKey, 0)), suffix="h", sizePolicy=self.size_policy, ) self.restMinutesSpinBox = QSpinBox( minimum=0, maximum=60, value=int(settings.value(restMinutesKey, 5)), suffix="m", sizePolicy=self.size_policy, ) self.restSecondsSpinBox = QSpinBox( minimum=0, maximum=60, value=int(settings.value(restSecondsKey, 0)), suffix="s", sizePolicy=self.size_policy, ) self.restGroupBoxLayout.addWidget(self.restHoursSpinBox) self.restGroupBoxLayout.addWidget(self.restMinutesSpinBox) self.restGroupBoxLayout.addWidget(self.restSecondsSpinBox) """ Create other groupbox""" self.otherGroupBox = QGroupBox("Other") self.otherGroupBoxLayout = QHBoxLayout(self.otherGroupBox) self.otherGroupBox.setLayout(self.otherGroupBoxLayout) self.repetitionsLabel = QLabel("Repetitions") self.repetitionsSpinBox = QSpinBox( minimum=0, maximum=10000, value=0, sizePolicy=self.size_policy, specialValueText="∞", ) self.modeLabel = QLabel("Mode") self.modeComboBox = QComboBox(sizePolicy=self.size_policy) self.modeComboBox.addItems(["work", "rest"]) self.otherGroupBoxLayout.addWidget(self.repetitionsLabel) self.otherGroupBoxLayout.addWidget(self.repetitionsSpinBox) self.otherGroupBoxLayout.addWidget(self.modeLabel) self.otherGroupBoxLayout.addWidget(self.modeComboBox) """ Create timer groupbox""" self.lcdDisplayGroupBox = QGroupBox("Time") self.lcdDisplayGroupBoxLayout = QHBoxLayout(self.lcdDisplayGroupBox) self.lcdDisplayGroupBox.setLayout(self.lcdDisplayGroupBoxLayout) self.timeDisplay = QLCDNumber(8, sizePolicy=self.size_policy) self.timeDisplay.setFixedHeight(100) self.timeDisplay.display("00:00:00") self.lcdDisplayGroupBoxLayout.addWidget(self.timeDisplay) """ Create pause, start and reset buttons""" self.buttonContainer = QWidget() self.buttonContainerLayout = QHBoxLayout(self.buttonContainer) self.buttonContainer.setLayout(self.buttonContainerLayout) self.startButton = self.makeButton("start", disabled=False) self.resetButton = self.makeButton("reset") self.pauseButton = self.makeButton("pause") """ Add widgets to container """ self.workGroupBoxLayout.addWidget(self.workHoursSpinBox) self.workGroupBoxLayout.addWidget(self.workMinutesSpinBox) self.workGroupBoxLayout.addWidget(self.workSecondsSpinBox) self.timerContainerLayout.addWidget(self.workGroupBox) self.timerContainerLayout.addWidget(self.restGroupBox) self.timerContainerLayout.addWidget(self.otherGroupBox) self.timerContainerLayout.addWidget(self.lcdDisplayGroupBox) self.buttonContainerLayout.addWidget(self.pauseButton) self.buttonContainerLayout.addWidget(self.startButton) self.buttonContainerLayout.addWidget(self.resetButton) self.timerContainerLayout.addWidget(self.buttonContainer) return self.timerContainer def setupTasksTab(self): settings = QSettings() """ Create vertical tasks container """ self.tasksWidget = QWidget(self.tabWidget) self.tasksWidgetLayout = QVBoxLayout(self.tasksWidget) self.tasksWidget.setLayout(self.tasksWidgetLayout) """ Create horizontal input container """ self.inputContainer = QWidget() self.inputContainer.setFixedHeight(50) self.inputContainerLayout = QHBoxLayout(self.inputContainer) self.inputContainerLayout.setContentsMargins(0, 0, 0, 0) self.inputContainer.setLayout(self.inputContainerLayout) """ Create text edit """ self.taskTextEdit = QTextEdit( placeholderText="Describe your task briefly.", undoRedoEnabled=True) """ Create vertical buttons container """ self.inputButtonContainer = QWidget() self.inputButtonContainerLayout = QVBoxLayout( self.inputButtonContainer) self.inputButtonContainerLayout.setContentsMargins(0, 0, 0, 0) self.inputButtonContainer.setLayout(self.inputButtonContainerLayout) """ Create buttons """ self.acceptTaskButton = QToolButton(icon=makeIcon("check")) self.deleteTaskButton = QToolButton(icon=makeIcon("trash")) """ Create tasks tablewidget """ self.tasksTableWidget = QTableWidget(0, 1) self.tasksTableWidget.setHorizontalHeaderLabels(["Tasks"]) self.tasksTableWidget.horizontalHeader().setStretchLastSection(True) self.tasksTableWidget.verticalHeader().setVisible(False) self.tasksTableWidget.setWordWrap(True) self.tasksTableWidget.setTextElideMode(Qt.TextElideMode.ElideNone) self.tasksTableWidget.setEditTriggers( QAbstractItemView.EditTriggers.NoEditTriggers) self.tasksTableWidget.setSelectionMode( QAbstractItemView.SelectionMode.SingleSelection) self.insertTasks(*settings.value(tasksKey, [])) """ Add widgets to container widgets """ self.inputButtonContainerLayout.addWidget(self.acceptTaskButton) self.inputButtonContainerLayout.addWidget(self.deleteTaskButton) self.inputContainerLayout.addWidget(self.taskTextEdit) self.inputContainerLayout.addWidget(self.inputButtonContainer) self.tasksWidgetLayout.addWidget(self.inputContainer) self.tasksWidgetLayout.addWidget(self.tasksTableWidget) return self.tasksWidget def setupStatisticsTab(self): """ Create statistics container """ self.statisticsContainer = QWidget() self.statisticsContainerLayout = QVBoxLayout(self.statisticsContainer) self.statisticsContainer.setLayout(self.statisticsContainerLayout) """ Create work time groupbox """ self.statisticsWorkTimeGroupBox = QGroupBox("Work Time") self.statisticsWorkTimeGroupBoxLayout = QHBoxLayout() self.statisticsWorkTimeGroupBox.setLayout( self.statisticsWorkTimeGroupBoxLayout) self.statisticsWorkTimeDisplay = QLCDNumber(8) self.statisticsWorkTimeDisplay.display("00:00:00") self.statisticsWorkTimeGroupBoxLayout.addWidget( self.statisticsWorkTimeDisplay) """ Create rest time groupbox """ self.statisticsRestTimeGroupBox = QGroupBox("Rest Time") self.statisticsRestTimeGroupBoxLayout = QHBoxLayout() self.statisticsRestTimeGroupBox.setLayout( self.statisticsRestTimeGroupBoxLayout) self.statisticsRestTimeDisplay = QLCDNumber(8) self.statisticsRestTimeDisplay.display("00:00:00") self.statisticsRestTimeGroupBoxLayout.addWidget( self.statisticsRestTimeDisplay) """ Create total time groupbox """ self.statisticsTotalTimeGroupBox = QGroupBox("Total Time") self.statisticsTotalTimeGroupBoxLayout = QHBoxLayout() self.statisticsTotalTimeGroupBox.setLayout( self.statisticsTotalTimeGroupBoxLayout) self.statisticsTotalTimeDisplay = QLCDNumber(8) self.statisticsTotalTimeDisplay.display("00:00:00") self.statisticsTotalTimeGroupBoxLayout.addWidget( self.statisticsTotalTimeDisplay) """ Add widgets to container """ self.statisticsContainerLayout.addWidget( self.statisticsTotalTimeGroupBox) self.statisticsContainerLayout.addWidget( self.statisticsWorkTimeGroupBox) self.statisticsContainerLayout.addWidget( self.statisticsRestTimeGroupBox) return self.statisticsContainer def setupTrayicon(self): self.trayIcon = QSystemTrayIcon(makeIcon("tomato")) self.trayIcon.setContextMenu(QMenu()) self.quitAction = self.trayIcon.contextMenu().addAction( makeIcon("exit"), "Quit", self.exit) self.quitAction.triggered.connect(self.exit) self.trayIcon.activated.connect(self.onActivate) self.trayIcon.show() self.trayIcon.setToolTip("Pomodoro") self.toast = ToastNotifier() def leaveEvent(self, event): super(MainWindow, self).leaveEvent(event) self.tasksTableWidget.clearSelection() def closeEvent(self, event): super(MainWindow, self).closeEvent(event) settings = QSettings() settings.setValue(workHoursKey, self.workHoursSpinBox.value()) settings.setValue( workMinutesKey, self.workMinutesSpinBox.value(), ) settings.setValue( workSecondsKey, self.workSecondsSpinBox.value(), ) settings.setValue(restHoursKey, self.restHoursSpinBox.value()) settings.setValue( restMinutesKey, self.restMinutesSpinBox.value(), ) settings.setValue( restSecondsKey, self.restSecondsSpinBox.value(), ) tasks = [] for i in range(self.tasksTableWidget.rowCount()): item = self.tasksTableWidget.item(i, 0) if not item.font().strikeOut(): tasks.append(item.text()) settings.setValue(tasksKey, tasks) def startTimer(self): try: if not self.timer.isActive(): self.createTimer() except: self.createTimer() def createTimer(self): self.timer = QTimer() self.timer.timeout.connect(self.updateTime) self.timer.timeout.connect(self.maybeChangeMode) self.timer.setInterval(1000) self.timer.setSingleShot(False) self.timer.start() def pauseTimer(self): try: self.timer.stop() self.timer.disconnect() except: pass def resetTimer(self): try: self.pauseTimer() self.time = QTime(0, 0, 0, 0) self.displayTime() except: pass def maybeStartTimer(self): if self.currentRepetitions != self.maxRepetitions: self.startTimer() started = True else: self.currentRepetitions = 0 started = False return started def updateWorkEndTime(self): self.workEndTime = QTime( self.workHoursSpinBox.value(), self.workMinutesSpinBox.value(), self.workSecondsSpinBox.value(), ) def updateRestEndTime(self): self.restEndTime = QTime( self.restHoursSpinBox.value(), self.restMinutesSpinBox.value(), self.restSecondsSpinBox.value(), ) def updateCurrentMode(self, mode: str): self.currentMode = Mode.work if mode == "work" else Mode.rest def updateTime(self): self.time = self.time.addSecs(1) self.totalTime = self.totalTime.addSecs(1) if self.modeComboBox.currentText() == "work": self.workTime = self.workTime.addSecs(1) else: self.restTime = self.restTime.addSecs(1) self.displayTime() def updateMaxRepetitions(self, value): if value == 0: self.currentRepetitions = 0 self.maxRepetitions = -1 else: self.maxRepetitions = 2 * value def maybeChangeMode(self): if self.currentMode is Mode.work and self.time >= self.workEndTime: self.resetTimer() self.modeComboBox.setCurrentIndex(1) self.incrementCurrentRepetitions() started = self.maybeStartTimer() self.showWindowMessage( Status.workFinished if started else Status.repetitionsReached) if not started: self.resetButton.click() elif self.currentMode is Mode.rest and self.time >= self.restEndTime: self.resetTimer() self.modeComboBox.setCurrentIndex(0) self.incrementCurrentRepetitions() started = self.maybeStartTimer() self.showWindowMessage( Status.restFinished if started else Status.repetitionsReached) if not started: self.resetButton.click() def incrementCurrentRepetitions(self): if self.maxRepetitions > 0: self.currentRepetitions += 1 def insertTask(self): task = self.taskTextEdit.toPlainText() self.insertTasks(task) def insertTasks(self, *tasks): for task in tasks: if task: rowCount = self.tasksTableWidget.rowCount() self.tasksTableWidget.setRowCount(rowCount + 1) self.tasksTableWidget.setItem(rowCount, 0, QTableWidgetItem(task)) self.tasksTableWidget.resizeRowsToContents() self.taskTextEdit.clear() def deleteTask(self): selectedIndexes = self.tasksTableWidget.selectedIndexes() if selectedIndexes: self.tasksTableWidget.removeRow(selectedIndexes[0].row()) def markTaskAsFinished(self, row, col): item = self.tasksTableWidget.item(row, col) font = self.tasksTableWidget.item(row, col).font() font.setStrikeOut(False if item.font().strikeOut() else True) item.setFont(font) def displayTime(self): self.timeDisplay.display(self.time.toString(self.timeFormat)) self.statisticsRestTimeDisplay.display( self.restTime.toString(self.timeFormat)) self.statisticsWorkTimeDisplay.display( self.workTime.toString(self.timeFormat)) self.statisticsTotalTimeDisplay.display( self.totalTime.toString(self.timeFormat)) def showWindowMessage(self, status): if status is Status.workFinished: title, text = "Break", choice(work_finished_phrases) elif status is Status.restFinished: title, text = "Work", choice(rest_finished_phrases) else: title, text = "Finished", choice(work_finished_phrases) self.trayIcon.showMessage(title, text, makeIcon("tomato")) self.toast.show_toast(title, text, icon_path="pomodoro/data/icons/tomato.ico", duration=10, threaded=True) def makeButton(self, text, iconName=None, disabled=True): button = QPushButton(text, sizePolicy=self.size_policy) if iconName: button.setIcon(makeIcon(iconName)) button.setDisabled(disabled) return button def exit(self): self.close() app = QApplication.instance() if app: app.quit() def onActivate(self, reason): if reason == QSystemTrayIcon.ActivationReason.Trigger: self.show()
class Ui_TrainPanel(object): def setupUi(self, TrainPanel): self.parent = TrainPanel self.mainLayout = QHBoxLayout(TrainPanel) self.bigFont = QLabel().font() self.bigFont.setPointSize(13) self.actionsLayout = QHBoxLayout(TrainPanel) # self.checkRecording = QCheckBox(TrainPanel) self.calibrateButton = QPushButton("Calibrate", parent=TrainPanel) self.calibrateButton.setFont(self.bigFont) self.calibrateButton.setStyleSheet(CustomQStyles.buttonStyle) self.calibrateButton.setMinimumHeight(50) self.calibrateButton.setMaximumWidth(170) self.calibrateButton.setMinimumWidth(120) self.sessionButton = QPushButton("Session", parent=TrainPanel) self.sessionButton.setFont(self.bigFont) self.sessionButton.setStyleSheet(CustomQStyles.outlineButtonStyle) self.sessionButton.setMinimumHeight(50) self.sessionButton.setMaximumWidth(170) self.sessionButton.setMinimumWidth(120) self.listFiles = QListWidget(TrainPanel) self.listFiles.setFont(self.bigFont) self.label = QLabel('or select', parent=TrainPanel) self.subjectLayout = QVBoxLayout(TrainPanel) print("init") self.box1 = QGroupBox(parent=TrainPanel) self.box2 = QGroupBox(parent=TrainPanel) self.wizard = CalibrateWizard(parent=TrainPanel) self.setPatientsBox(TrainPanel) # right panel self.setActionsBox(TrainPanel) # left panel self.mainLayout.addWidget(self.box1, stretch=2) self.mainLayout.addWidget(self.box2, stretch=3) # self.mainLayout.setAlignment(self.box2, Qt.Alignment.AlignCenter) # Display progress bar, checkbox - to record new gestures or not, start train def setActionsBox(self, TrainPanel): hLayout = QVBoxLayout() hLayout.addWidget(self.calibrateButton) hLayout.addWidget(self.sessionButton) hLayout.setAlignment(self.calibrateButton, Qt.Alignment.AlignCenter) hLayout.setAlignment(self.sessionButton, Qt.Alignment.AlignCenter) self.box2.setLayout(hLayout) # Display list of subjects, or new subject def setPatientsBox(self, TrainPanel): # Button to create new patient self.addPatient = QPushButton('Create Patient') self.addPatient.setFixedSize(120, 35) self.addPatient.setStyleSheet(CustomQStyles.outlineButtonStyle) self.label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) self.label.setAlignment(QtCore.Qt.Alignment.AlignCenter) self.loadPatientList() self.listFiles.setStyleSheet(CustomQStyles.listStyle) self.listFiles.setFocusPolicy(Qt.FocusPolicy.NoFocus) self.subjectLayout.addWidget(self.addPatient) self.subjectLayout.setAlignment(self.addPatient, Qt.Alignment.AlignCenter) self.subjectLayout.addWidget(self.label) self.subjectLayout.addWidget(self.listFiles) self.box1.setLayout(self.subjectLayout) def loadPatientList(self): self.listFiles.clear() self.parent.patients.clear() files = [ f for f in listdir(PATIENTS_PATH) if isfile(join(PATIENTS_PATH, f)) ] for x, ind in zip(files, range(0, len(files))): item = QListWidgetItem(x.split('.')[0]) item.setTextAlignment(Qt.Alignment.AlignHCenter) self.listFiles.addItem(item) with open(PATIENTS_PATH + x, 'r') as f: person_dict = json.load(f) patient = Patient(person_dict['Name'], person_dict['Age'], person_dict['Exercises']) self.parent.patients.append(patient) print(self.parent.patients) def deleteItemsOfLayout(self, layout): if layout is not None: while layout.count(): item = layout.takeAt(0) widget = item.widget() if widget is not None: widget.setParent(None) else: self.deleteItemsOfLayout(item.layout())
class Window(QDialog): def __init__(self): super(Window, self).__init__() self.groupBox = QGroupBox( "What is your favorite programming Language ?") self.groupBox.setFont(QFont("Sanserif", 13)) self.checkBox1 = QCheckBox("Python") self.checkBox1.setIcon(QIcon("")) self.checkBox1.setWhatsThis("This is a checkbox of Python") self.checkBox2 = QCheckBox("C++") self.checkBox2.setIcon(QIcon("")) self.checkBox1.setWhatsThis("This is a checkbox of C++") self.checkBox3 = QCheckBox("Java") self.checkBox3.setIcon(QIcon("")) self.checkBox1.setWhatsThis("This is a checkbox of Java") self.label = QLabel("You Have Selected FootBall") self.title = " " self.left = 100 self.top = 200 self.width = 400 self.height = 300 self.InitWindow() def InitWindow(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.createCheckBox() vbox = QVBoxLayout() vbox.addWidget(self.groupBox) vbox.addWidget(self.label) self.setLayout(vbox) self.show() def createCheckBox(self): hboxLayout = QHBoxLayout() self.checkBox1.toggled.connect(self.onCheckBox_Toggled) hboxLayout.addWidget(self.checkBox1) self.checkBox2.toggled.connect(self.onCheckBox_Toggled) hboxLayout.addWidget(self.checkBox2) self.checkBox3.toggled.connect(self.onCheckBox_Toggled) hboxLayout.addWidget(self.checkBox3) self.groupBox.setLayout(hboxLayout) def onCheckBox_Toggled(self): if self.checkBox1.isChecked(): self.label.setText("You Have Select : " + self.checkBox1.text()) if self.checkBox2.isChecked(): self.label.setText("You Have Select : " + self.checkBox2.text()) if self.checkBox3.isChecked(): self.label.setText("You Have Select : " + self.checkBox3.text())
def __init__( self, onPlayButtonPressed: Callable[[], None], onPauseButtonPressed: Callable[[], None], onStepButtonPressed: Callable[[], None], onRestartButtonPressed: Callable[[], None], onSpeedControlValueChanged: Callable[[int], None], onOpenLogButtonPressed: Callable[[], None], onAgentVarsButtonPressed: Callable[[], None], onSolveButtonPressed: Callable[[MazeSolverSpecification], None], mazeSize: XY, parent: Optional[QWidget] = None, *args: Tuple[Any, Any], **kwargs: Tuple[Any, Any], ) -> None: """ Grouped controls box for controls for solving mazes """ self.__onSolveButtonPressed = onSolveButtonPressed self.__mazeSize = mazeSize self.__maximumXY = XY( self.__mazeSize.x - 1, self.__mazeSize.y - 1, ) super().__init__(parent=parent, *args, **kwargs) self.setContentsMargins(0, 0, 0, 0) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) groupbox = QGroupBox("Solve Maze") layout.addWidget(groupbox) vbox = QFormLayout() groupbox.setLayout(vbox) self.__startPosition = XYPicker( minimum=XY(0, 0), maximum=self.__maximumXY, initialValue=XY(0, 0), parent=self, label="•", ) self.__endPosition = XYPicker( minimum=XY(0, 0), maximum=self.__maximumXY, initialValue=self.__maximumXY, parent=self, label="•", ) self.__solverTypePicker = QComboBox(self) self.__solverTypePicker.addItem("Wall Follower", WallFollower) self.__solverTypePicker.addItem("Pledge Solver", PledgeSolver) self.__solverTypePicker.addItem("Random Mouse", RandomMouse) solveButton = QPushButton("Solve") solveButton.clicked.connect( # type: ignore lambda: self.__onSolveButtonPressed( MazeSolverSpecification( startPosition=self.__startPosition.getValues(), endPosition=self.__endPosition.getValues(), solverType=self.__solverTypePicker.currentData(), ), ) ) self.__solverControlsDropdown = SolverControlsView( onPlayButtonPressed=onPlayButtonPressed, onPauseButtonPressed=onPauseButtonPressed, onStepButtonPressed=onStepButtonPressed, onRestartButtonPressed=onRestartButtonPressed, onSpeedControlValueChanged=onSpeedControlValueChanged, onOpenLogButtonPressed=onOpenLogButtonPressed, onAgentVarsButtonPressed=onAgentVarsButtonPressed, parent=self, ) # connect enable/disable signal to child view self.setMazeSolverControlsEnabled.connect( self.__solverControlsDropdown.setMazeSolverControlsEnabled ) vbox.addRow("Start Position", self.__startPosition) vbox.addRow("End Position", self.__endPosition) vbox.addRow("Solver Type", self.__solverTypePicker) vbox.addRow(solveButton) vbox.addRow(self.__solverControlsDropdown) self.setLayout(layout)
def __init__(self, parent: QWidget): super().__init__() self.logger = logging.getLogger(__name__) with open(file="config.json", mode="r", encoding="utf-8") as conf_reader: self.conf = json.loads(conf_reader.read()) self.logger.debug("初始化设置界面。设置内容:%s" % self.conf) layout = QGridLayout() self.setLayout(layout) self.setModal(True) self.setParent(parent) self.resize(400, 300) title = QLabel("设置") title.setStyleSheet( "QLabel{border:none;border-radius:5px;background:transparent;color:#9AD3BC;font-size:20px;}" ) title.setAlignment(Qt.Alignment.AlignCenter) layout.addWidget(title, 0, 1, Qt.Alignment.AlignCenter) control_close = QPushButton() control_close.setStyleSheet( "QPushButton{background:#FFE3ED;border-radius:5px;border:none;}QPushButton:hover{background:#EC524B;}" ) control_close.setToolTip("关闭") control_close.setFixedHeight(20) control_close.clicked.connect(self.close_callback) layout.addWidget(control_close, 0, 0) debug_check = QCheckBox("调试模式") debug_check.setChecked(self.conf["debug"]) debug_check.setToolTip("单击切换开关状态") debug_check.setStyleSheet( "QCheckBox::indicator{width:10px;height:10px;border:none;border-radius:5px;background:#9BE3DE;}QCheckBox::indicator:unchecked{background:#BEEBE9;}QCheckBox::indicator:unchecked:hover{background:#9AD3BC;}QCheckBox::indicator:checked{background:#95E1D3;}QCheckBox::indicator:checked:hover{background:#98DED9;}" ) self.content = QGridLayout() (x, y) = self.show_setting(conf=self.conf, layout=self.content) # 返回content的最后一个元素的x,y proxy = QGroupBox() proxy.setObjectName("proxy") proxy_layout = QVBoxLayout() proxy_label = QLabel("代理地址:") proxy_label.setStyleSheet( "QLabel{background:transparent;border:none;}") proxy_input = EnhancedEdit() proxy_input.setText(self.conf["proxy"]) proxy_input.setToolTip("格式为协议://IP:端口,留空保持直连") proxy_input.setStyleSheet( "QLineEdit{border:1px solid #F3EAC2;border-radius:5px;background:transparent;}QLineEdit:hover{border:1px solid #F5B461;}" ) proxy_layout.addWidget(proxy_label) proxy_layout.addWidget(proxy_input) proxy.setLayout(proxy_layout) proxy.setStyleSheet("QGroupBox{border-radius:5px;}") proxy.setToolTip("代理设置") if y + 1 >= 3: y_ = 0 x_ = x + 1 else: y_ = y + 1 x_ = x self.content.addWidget(proxy, x_, y_) self.content.addWidget(debug_check) layout.addLayout(self.content, 1, 1)
class MainWindowWidget(QWidget): """ 主窗口界面 搜索框+tab页 """ load_comic_list_signa = QtCore.pyqtSignal(ComicInfo) def __init__(self, main_window: QWidget): super().__init__() self.search_callback = None # 主题空间 子组件都放这个Widget里 self.centralWidget = QtWidgets.QWidget(main_window) self.centralWidget.setObjectName("centralWidget") # 搜索框 self.souInput = QtWidgets.QLineEdit(self.centralWidget) self.souInput.setGeometry(QtCore.QRect(40, 30, 800, 30)) font = QtGui.QFont() font.setPointSize(22) font.setKerning(True) font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferDefault) self.souInput.setFont(font) self.souInput.setObjectName("souInput") self.souInput.setText("龙珠") self.modBox = CheckableComboBox(self.centralWidget) self.modBox.setGeometry(QtCore.QRect(850, 30, 120, 30)) for k in constant.mod_dist.keys(): if k in constant.mod_list: self.modBox.addItem(QtCore.Qt.CheckState.Checked, k) else: self.modBox.addItem(QtCore.Qt.CheckState.Unchecked, k) # QTabWidget tab页签 self.tabWidget = QtWidgets.QTabWidget(self.centralWidget) self.tabWidget.setGeometry(QtCore.QRect(40, 70, 944, 668)) self.tabWidget.setTabsClosable(True) self.tabWidget.setObjectName("tabWidget") # 下载页面 self.down_tab = QtWidgets.QWidget() self.down_tab.setStatusTip("") self.down_tab.setAutoFillBackground(False) self.down_tab.setObjectName("down_tab") self.tabWidget.addTab(self.down_tab, "下载列表") # 书架页面 self.bookshelf_tab = QtWidgets.QWidget() self.bookshelf_tab.setObjectName("bookshelf_tab") self.tabWidget.addTab(self.bookshelf_tab, "书架") # 搜索结果页面 self.search_tab = QtWidgets.QWidget() self.search_tab.setObjectName("search_tab") self.tabWidget.addTab(self.search_tab, "搜索结果") # None 空按钮,tab签右侧按钮,设置到前面 tbr = self.tabWidget.tabBar().tabButton(0, QTabBar.ButtonPosition.RightSide) self.tabWidget.tabBar().setTabButton(0, QTabBar.ButtonPosition.LeftSide, tbr) self.tabWidget.tabBar().setTabButton(1, QTabBar.ButtonPosition.LeftSide, tbr) self.tabWidget.tabBar().setTabButton(2, QTabBar.ButtonPosition.LeftSide, tbr) # 启用关闭页签的功能 self.tabWidget.tabCloseRequested.connect(self.tab_close) # 默认打开到书架 self.tabWidget.setCurrentIndex(1) # 主体的centralWidget 放到主窗口中 main_window.setCentralWidget(self.centralWidget) # 书架页 self.bookshelfVBoxLayout = QVBoxLayout() self.bookshelfGroupBox = QGroupBox() self.bookshelfScroll = QScrollArea() self.bookshelfLayout = QVBoxLayout(self.bookshelf_tab) self.bookshelfVBoxLayout.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) self.bookshelfGroupBox.setLayout(self.bookshelfVBoxLayout) self.bookshelfScroll.setWidget(self.bookshelfGroupBox) self.bookshelfScroll.setWidgetResizable(True) self.bookshelfLayout.addWidget(self.bookshelfScroll) # 搜索页 self.searchVBoxLayout = QVBoxLayout() self.searchGroupBox = QGroupBox() self.searchScroll = QScrollArea() self.searchLayout = QVBoxLayout(self.search_tab) self.searchVBoxLayout.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) self.searchGroupBox.setLayout(self.searchVBoxLayout) self.searchScroll.setWidget(self.searchGroupBox) self.searchScroll.setWidgetResizable(True) self.searchLayout.addWidget(self.searchScroll) # 下载页 self.downVBoxLayout = QVBoxLayout() self.downGroupBox = QGroupBox() self.downScroll = QScrollArea() self.downLayout = QVBoxLayout(self.down_tab) self.downVBoxLayout.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) self.downGroupBox.setLayout(self.downVBoxLayout) self.downScroll.setWidget(self.downGroupBox) self.downScroll.setWidgetResizable(True) self.downLayout.addWidget(self.downScroll) down_button_layout = QHBoxLayout() self.downLayout.addLayout(down_button_layout) down_button_layout.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight) all_start = QPushButton() all_start.setText("全部开始") all_stop = QPushButton() all_stop.setText("全部停止") clear_done = QPushButton() clear_done.setText("清理已完成") down_button_layout.addWidget(all_start) down_button_layout.addWidget(all_stop) down_button_layout.addWidget(clear_done) self.souInput.returnPressed.connect(self.input_return_pressed) # 回车搜索 self.load_comic_list_signa.connect(self.search_load_comic_list) # 更新ui的插槽 self.bookshelf_load_comic_list() self.download_callback() def tab_close(self, index): """ 关闭tab,删掉缓存的列表 :param index: tab索引 :return: """ self.tabWidget.removeTab(index) del constant.OPEN_TAB[index - 3] def input_return_pressed(self): """ 搜索框回车函数 :return: """ for i in range(self.searchVBoxLayout.count()): # 清理显示的内容 self.searchVBoxLayout.itemAt(i).widget().deleteLater() constant.mod_list.clear() for i in range(self.modBox.count()): if self.modBox.item_checked(i): constant.mod_list.add(self.modBox.model().item(i).text()) if len(constant.mod_list) > 0: constant.SERVICE.search(self.souInput.text(), self.load_comic_list_signa.emit) # 查询回调出发插槽 self.tabWidget.setCurrentIndex(2) def search_load_comic_list(self, info: ComicInfo): """ 解析的漫画信息,通过回调到本方法,加载页面 :param info: :return: """ # 加载到展示视图,需要判断你,是否还是之前的搜索项 if self.souInput.text() == info.searchKey: comic_info_widget = UIComicListWidget(info, self.tabWidget, self.downVBoxLayout) self.searchVBoxLayout.addWidget(comic_info_widget) def bookshelf_load_comic_list(self): for item in constant.downloaded_comic_map.values(): comic_info_widget = UIComicListWidget(item, self.tabWidget, self.downVBoxLayout) self.bookshelfVBoxLayout.addWidget(comic_info_widget) def download_callback(self): for item in constant.downloaded_task_map.values(): widget = DownLoadTaskWidget(item) widget.update_task(item) self.downVBoxLayout.addWidget(widget)
class MainWindow(QMainWindow): def __init__(self, admin_or_not=None): """ MainWindow Constructor """ super().__init__() self.admin_or_not = admin_or_not # Used to grant the user admin privileges self.curr_proxy_model = None # Variable that refers to the current page's proxy mmodel self.initializeUI() def initializeUI(self): """Set up the GUI's main window.""" self.setWindowTitle("Database Manager") self.setMinimumSize(800, 400) self.setUpMainWindow() def setUpMainWindow(self): """Create and arrange widgets in the main window.""" # Create the container widget for each of the pages # in the tab widget self.customer_tab = QWidget() self.orders_tab = QWidget() self.category_tab = QWidget() self.products_tab = QWidget() # Add or insert the tabs into the tab widget self.tabs = QTabWidget() self.tabs.setDocumentMode(True) self.tabs.addTab(self.customer_tab, "Customers") self.tabs.addTab(self.orders_tab, "Orders") self.tabs.addTab(self.category_tab, "Categories") self.tabs.addTab(self.products_tab, "Products") if self.admin_or_not == 1: self.staff_tab = QWidget() self.tabs.insertTab(0, self.staff_tab, "Staff") self.createStaffTab() self.tabs.setCurrentIndex(1) # Set tab to Customers tab self.tabs.currentChanged.connect(self.updateWidgetsAndStates) # Call the methods to construct each page self.createCustomersTab() self.createOrdersTab() self.createCategoriesTab() self.createProductsTab() # Create the widgets in the sidebar for filtering table content self.table_name_label = QLabel("<b>Customers</b>") self.table_name_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.filter_pattern_line = QLineEdit() self.filter_pattern_line.setClearButtonEnabled(True) self.filter_pattern_line.textChanged.connect(self.filterRegExpChanged) self.filter_regex_combo = QComboBox() filter_options = ["Default", "Wildcard", "Fixed String"] self.filter_regex_combo.addItems(filter_options) self.filter_regex_combo.currentIndexChanged.connect( self.filterRegExpChanged) self.filter_field_combo = QComboBox() self.updateWidgetsAndStates( 1) # Initialize the values in filter_field_combo self.filter_field_combo.currentIndexChanged.connect( self.selectTableColumn) filter_case_sensitivity_cb = QCheckBox("Filter with Case Sensitivity") filter_case_sensitivity_cb.toggled.connect(self.toggleCaseSensitivity) filter_case_sensitivity_cb.toggle() # Layout for the sidebar filter_v_box = QVBoxLayout() filter_v_box.addWidget(self.table_name_label) filter_v_box.addWidget(QLabel("Filter Pattern")) filter_v_box.addWidget(self.filter_pattern_line) filter_v_box.addWidget(QLabel("Filter filter")) filter_v_box.addWidget(self.filter_regex_combo) filter_v_box.addWidget(QLabel("Select Table Column")) filter_v_box.addWidget(self.filter_field_combo) filter_v_box.addWidget(filter_case_sensitivity_cb) filter_v_box.addStretch(2) self.filter_group = QGroupBox("Filtering") self.filter_group.setMaximumWidth(260) self.filter_group.setLayout(filter_v_box) # Arrange the containers in the main window main_h_box = QHBoxLayout() main_h_box.addWidget(self.tabs) main_h_box.addWidget(self.filter_group) main_container = QWidget() main_container.setLayout(main_h_box) self.setCentralWidget(main_container) # Create status bar self.setStatusBar(QStatusBar()) def createStaffTab(self): """Create the page to view the Staff table from the database.""" staff_sql_model = QSqlRelationalTableModel() staff_sql_model.setTable("Staff") staff_sql_model.select() # Populate the model with data staff_proxy_model = QSortFilterProxyModel() staff_proxy_model.setSourceModel(staff_sql_model) staff_table = QTableView() staff_table.setSortingEnabled(True) staff_table.setModel(staff_proxy_model) staff_table.setItemDelegateForColumn( staff_sql_model.fieldIndex("staff_id"), ReadOnlyDelegate()) staff_table.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeMode.Stretch) staff_h_box = QHBoxLayout() staff_h_box.addWidget(staff_table) self.staff_tab.setLayout(staff_h_box) def createCustomersTab(self): """Create the page to view the Customers table from the database.""" cust_sql_model = QSqlRelationalTableModel() cust_sql_model.setTable("Customers") cust_sql_model.setRelation( cust_sql_model.fieldIndex("staff_id"), QSqlRelation("Staff", "staff_id", "username")) cust_sql_model.setHeaderData(cust_sql_model.fieldIndex("staff_id"), Qt.Orientation.Horizontal, "staff_username") cust_sql_model.select() # Populate the model with data cust_proxy_model = QSortFilterProxyModel() cust_proxy_model.setSourceModel(cust_sql_model) cust_table = QTableView() cust_table.setSortingEnabled(True) cust_table.setModel(cust_proxy_model) cust_table.setItemDelegate(SqlProxyDelegate(cust_table)) cust_table.setItemDelegateForColumn(cust_sql_model.fieldIndex("phone"), PhoneDelegate()) cust_table.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeMode.Stretch) cust_h_box = QHBoxLayout() cust_h_box.addWidget(cust_table) self.customer_tab.setLayout(cust_h_box) def createOrdersTab(self): """Create the page to view the Orders table from the database.""" ord_sql_model = QSqlRelationalTableModel() ord_sql_model.setTable("Orders") ord_sql_model.setRelation( ord_sql_model.fieldIndex("product_id"), QSqlRelation("Products", "product_id", "product_name")) ord_sql_model.setRelation( ord_sql_model.fieldIndex("customer_id"), QSqlRelation("Customers", "customer_id", "first_name")) ord_sql_model.setHeaderData(ord_sql_model.fieldIndex("customer_id"), Qt.Orientation.Horizontal, "customer_name") ord_sql_model.select() # Populate the model with data ord_proxy_model = QSortFilterProxyModel() ord_proxy_model.setSourceModel(ord_sql_model) ord_table = QTableView() ord_table.setSortingEnabled(True) ord_table.setModel(ord_proxy_model) ord_table.setItemDelegate(SqlProxyDelegate(ord_table)) ord_table.setItemDelegateForColumn( ord_sql_model.fieldIndex("date_of_order"), DateDelegate()) ord_table.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeMode.Stretch) ord_h_box = QHBoxLayout() ord_h_box.addWidget(ord_table) self.orders_tab.setLayout(ord_h_box) def createCategoriesTab(self): """Create the page to view the Categories table from the database.""" cat_sql_model = QSqlRelationalTableModel() cat_sql_model.setTable("Categories") cat_sql_model.select() # Populate the model with data cat_proxy_model = QSortFilterProxyModel() cat_proxy_model.setSourceModel(cat_sql_model) cat_table = QTableView() cat_table.setSortingEnabled(True) cat_table.setModel(cat_proxy_model) cat_table.setItemDelegateForColumn( cat_sql_model.fieldIndex("category_id"), ReadOnlyDelegate()) cat_table.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeMode.Stretch) cat_h_box = QHBoxLayout() cat_h_box.addWidget(cat_table) self.category_tab.setLayout(cat_h_box) def createProductsTab(self): """Create the page to view the Products table from the database.""" prod_sql_model = QSqlRelationalTableModel() prod_sql_model.setTable("Products") prod_sql_model.setRelation( prod_sql_model.fieldIndex("category_id"), QSqlRelation("Categories", "category_id", "category_name")) prod_sql_model.select() # Populate the model with data prod_proxy_model = QSortFilterProxyModel() prod_proxy_model.setSourceModel(prod_sql_model) prod_table = QTableView() prod_table.setSortingEnabled(True) prod_table.setModel(prod_proxy_model) prod_table.setItemDelegate(SqlProxyDelegate(prod_table)) prod_table.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeMode.Stretch) prod_h_box = QHBoxLayout() prod_h_box.addWidget(prod_table) self.products_tab.setLayout(prod_h_box) def filterRegExpChanged(self, value): """Slot for collecting the expression (pattern) for filtering items in the tables. Expressions are then passed to various QSortFilterProxyModel methods depending upon the value in filter_regex_combo.""" pattern = self.filter_pattern_line.text() filter = self.filter_regex_combo.currentText() model = self.curr_proxy_model if filter == "Wildcard": regex = QRegularExpression() pattern = regex.wildcardToRegularExpression( pattern, regex.WildcardConversionOption.UnanchoredWildcardConversion) elif filter == "Fixed String": pattern = QRegularExpression.escape(pattern) option = QRegularExpression.PatternOption.NoPatternOption regex = QRegularExpression(pattern, option) # Check whether or not the regular expression is valid or not if regex.isValid(): model.setFilterRegularExpression(regex) else: # Display error message in the statusbar self.statusBar().showMessage(regex.errorString(), 4000) model.setFilterRegularExpression(QRegularExpression()) def selectTableColumn(self, index): """Select the field (column) in the SQL table to be filtered.""" self.curr_proxy_model.setFilterKeyColumn(index) def toggleCaseSensitivity(self, toggled): """Toggle whether items are filtered with or without case sensitivity.""" if toggled: self.curr_proxy_model.setFilterCaseSensitivity( Qt.CaseSensitivity.CaseSensitive) else: self.curr_proxy_model.setFilterCaseSensitivity( Qt.CaseSensitivity.CaseInsensitive) def updateWidgetsAndStates(self, index): """Whenever the user switches a tab, update information regarding the tab selected, the current table's QSortFilterProxyModel, and information displayed in the sidebar for filtering.""" self.filter_field_combo.clear() curr_table = self.tabs.currentWidget().findChild(QTableView) curr_model = curr_table.model().sourceModel() # Set text to display current table's name in the sidebar self.table_name_label.setText(f"<b>{curr_model.tableName()}</b>") self.curr_proxy_model = curr_table.model() # Update QComboBox values based on currently selected tab field_names = [] for col in range(0, curr_model.columnCount()): field_names.append(curr_model.record().fieldName(col)) if curr_model.tableName() == "Orders" and \ "first_name" in field_names: field_names = [ "customer_name" if n == "first_name" else n for n in field_names ] self.filter_field_combo.addItems(field_names) # NOTE: To the reader, the following code differs slightly from the book. # This portion is left here as reference should you need to use both # QSqlTableModel and QSqlRelationalTableModel classes. Simply replace the code # above with the code below. """ if isinstance(curr_table.model(), QSqlRelationalTableModel): self.table_name_label.setText(f"<b>{curr_table.model().tableName()}</b>") # Update QComboBox values based on currently selected tab for col in range(0, curr_table.model().columnCount()): field_names.append(curr_table.model().record().fieldName(col)) self.filter_field_combo.addItems(field_names) elif isinstance(curr_table.model(), QSortFilterProxyModel): self.table_name_label.setText(f"<b>{curr_model.tableName()}</b>") self.curr_proxy_model = curr_table.model() # Update QComboBox values based on currently selected tab for col in range(0, curr_model.columnCount()): field_names.append(curr_model.record().fieldName(col)) if "first_name" in field_names: field_names = ["customer_name" if i=="first_name" else i for i in field_names] self.filter_field_combo.addItems(field_names) """ def closeEvent(self, event): """Close database connection when window is closed.""" model = self.curr_proxy_model.sourceModel() model.database().close()
class UIComicInfoWidget(QWidget): load_chapter_list_signa = QtCore.pyqtSignal(ChapterInfo) load_download_task_signa = QtCore.pyqtSignal(DownloadTask) def __init__(self, comic_info: ComicInfo, down_v_box_layout: QVBoxLayout): super().__init__() self.comic_info = comic_info self.down_v_box_layout = down_v_box_layout self.img_label = QLabel(self) self.img_label.setScaledContents(True) img = QImage.fromData(comic_info.cover) w, h = image_resize(comic_info.cover, width=200) self.img_label.resize(QtCore.QSize(w, h)) self.img_label.setGeometry(10, 10, w, h) self.img_label.setPixmap(QPixmap.fromImage(img)) # self.img_label.setPixmap(QtGui.QPixmap("/Users/bo/my/tmp/老夫子2/第1卷/1.jpg")) self.title = QLabel(self) self.title.setGeometry(220, 10, 100, 40) title_font = QtGui.QFont() title_font.setPointSize(16) title_font.setBold(True) title_font.setUnderline(True) self.title.setFont(title_font) self.title.setText(comic_info.title) self.title.setWordWrap(True) info_font = QtGui.QFont() info_font.setPointSize(14) # 作者 self.author = QLabel(self) self.author.setText("作者 : " + comic_info.author) self.author.setGeometry(220, 50, 150, 40) self.author.setWordWrap(True) self.author.setFont(info_font) # 状态 self.status = QLabel(self) self.status.setText("更新状态 : " + comic_info.status) self.status.setGeometry(220, 90, 150, 40) self.status.setFont(info_font) # 热度 self.heat = QLabel(self) self.heat.setText("热度 : " + str(comic_info.heat)) self.heat.setGeometry(220, 130, 150, 40) self.heat.setFont(info_font) # 类型 self.tip = QLabel(self) self.tip.setText("类型 : " + comic_info.tip) self.tip.setGeometry(220, 170, 150, 40) self.tip.setWordWrap(True) self.tip.setFont(info_font) # web self.domain = QLabel(self) self.domain.setText(f"查看原网页 : {comic_info.domain}") self.domain.setText(f'查看原网页 : <a href="{comic_info.url}">{comic_info.domain}</a>') self.domain.setGeometry(220, 210, 150, 40) self.domain.setOpenExternalLinks(True) self.domain.setFont(info_font) # 描述 self.describe = QLabel(self) self.describe.setText(" " + comic_info.describe) self.describe.setGeometry(10, 320, 350, 330) self.describe.setWordWrap(True) # 对齐方式 self.describe.setAlignment( QtCore.Qt.AlignmentFlag.AlignLeading | QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignTop) # 章节列表,创建一个区域 self.searchHBoxLayout = QHBoxLayout() # self.searchHBoxLayout.addSpacing() self.searchGroupBox = QGroupBox() self.searchGroupBox.setLayout(self.searchHBoxLayout) self.searchScroll = QScrollArea(self) self.searchScroll.setGeometry(370, 10, 574, 590) self.searchScroll.setWidget(self.searchGroupBox) self.searchScroll.setWidgetResizable(True) # 全选 self.check_all = QCheckBox(self) self.check_all.setText("全选") self.check_all.setGeometry(700, 610, 100, 20) self.check_all.stateChanged.connect(self.check_all_fun) # 下载 self.down_button = QPushButton(self) self.down_button.setText("下载") self.down_button.setGeometry(780, 605, 50, 30) self.down_button.clicked.connect(self.download_button_click) self.load_chapter_list_signa.connect(self.load_chapter) self.load_download_task_signa.connect(self.download_callback) # 调用对应的service的接口,获取章节列表 constant.SERVICE.chapter(comic_info, self.load_chapter_list_signa.emit) i = 0 searchVBoxLayout: QVBoxLayout check_box_list: List[QCheckBox] = [] def check_all_fun(self): for check_box in self.check_box_list: check_box.setChecked(self.check_all.isChecked()) def download_callback(self, task: DownloadTask): widget = DownLoadTaskWidget(task) self.down_v_box_layout.addWidget(widget) def download_button_click(self): flag = False for check_box in self.check_box_list: if check_box.isChecked(): constant.SERVICE.parse_image(self.comic_info, check_box.property("chapter_info"), self.load_download_task_signa.emit) if not flag: QMessageBox.information(self, "下载通知", "正在解析选中章节", QMessageBox.StandardButton.Yes) flag = True def load_chapter(self, chapter_info: ChapterInfo): if self.i % 26 == 0: self.searchVBoxLayout = QVBoxLayout() self.searchVBoxLayout.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) # 对齐方式,研究了3个小时 o(╥﹏╥)o self.searchHBoxLayout.addLayout(self.searchVBoxLayout) check_box = QCheckBox() self.check_box_list.append(check_box) check_box.setText(chapter_info.title) check_box.setProperty("chapter_info", chapter_info) task = constant.downloaded_task_map.get(chapter_info.url) if task and task.status == -1: check_box.setStyleSheet('color:red') check_box.setChecked(True) self.searchVBoxLayout.addWidget(check_box) self.i += 1