Pyqt5和线程 - 从外部类(方法)传递值不起作用 - 属性错误

问题描述 投票:0回答:1

我有主类与子类作为选项卡。我有这样的GUI:gui

QApp.py - Mainwindow

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PyQt5 import QtGui, QtWidgets
from QFilesTab import Files
from QWebservicesTab import Webservices
import qdarkstyle


class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
    super().__init__()

    self.task_bar()
    self.tab_layout()
    self.graph_elements()
    self.center()

def task_bar(self):
    ### actions on meenubar
    exitAct = QtWidgets.QAction('&Exit', self, shortcut='Ctrl+Q', statusTip='Exit application')
    exitAct.triggered.connect(self.close)
    moreinfo = QtWidgets.QAction('&Help', self, statusTip='More information')
    moreinfo.triggered.connect(self.information)

    ### menubar
    menubar = self.menuBar()
    fileMenu = menubar.addMenu('&File')
    fileMenu.addAction(exitAct)
    fileMenu = menubar.addMenu('&Help')
    fileMenu.addAction(moreinfo)

def graph_elements(self):
    ### basic geometry and color
    self.setWindowTitle('Villain')
    self.setWindowIcon(QtGui.QIcon('dc1.png'))
    self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))

def tab_layout(self):
    self.tabwidget = QtWidgets.QTabWidget()
    self.tabwidget.addTab(Files(), 'Files Import') ### ADDED SUB_CLASS AS QTABWIDGET
    self.tabwidget.addTab(Webservices(), 'Webservice')
    self.setCentralWidget(self.tabwidget)

### center main window
def center(self):
    qr = self.frameGeometry()
    cp = QtWidgets.QDesktopWidget().availableGeometry().center()
    qr.moveCenter(cp)
    self.move(qr.topLeft())

def information(self):
    QtWidgets.QMessageBox.information(self,'Information','Version: 2.0\n'\
                                        'Please, contact [email protected] for comments and suggestions\n\n'\
                                      'Digital Care - Data Processing Team')

这是我的子类,我在屏幕上显示为“文件导入”选项卡。我必须使用凭据来连接sql。所以我会尝试从我的__main__获取它

QFilesTab.py - 作为qtabwidget的子类

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import threading
from PyQt5 import QtGui, QtWidgets, QtCore
import pyodbc



class Files(QtWidgets.QWidget):
def __init__(self):
    super().__init__()
    self.layout_init()

def layout_init(self):
    operator = ['TMobile', 'PLK', 'Play', 'Orange']
    variant = ['Select variant', 'Numer usługi/polisy', 'IMEI', 'PESEL', 'NIP',
                'REGON', 'Nazwisko', 'Nazwa firmy']
    ###partners
    self.pvbox = QtWidgets.QVBoxLayout()
    self.buttongroup = QtWidgets.QButtonGroup(self)
    for elements, forms in enumerate(operator):
        element = str(forms)
        self.partners = QtWidgets.QRadioButton(element)
        self.buttongroup.addButton(self.partners, )
        self.pvbox.addWidget(self.partners,)
    self.buttongroup.buttonClicked.connect(self.on_itemSelected)
    self.buttongroup.buttonClicked['int'].connect(self.on_itemSelected)


    ###variants
    self.variants = QtWidgets.QComboBox()
    for elements, forms in enumerate(variant):
        element = str(forms)
        self.variants.addItem(element)
    self.variants.model().item(0).setEnabled(False)
    self.variants.activated.connect(self.update_textbox)

    self.textbox = QtWidgets.QLineEdit()

    self.tablewidget = QtWidgets.QTableWidget()
    self.tablewidget.setColumnCount(5)
    self.tablewidget.setHorizontalHeaderLabels(['FileNameOriginal', 'OrderItemCode', 'Imported','InfoCode', 'Row'])
    self.tablewidget.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
    self.tablewidget.horizontalHeader().setStretchLastSection(True)
    self.tablewidget.resizeColumnsToContents()
    self.tablewidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
    self.tablewidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)

    self.pb = QtWidgets.QPushButton(self.tr('Run process'))
    self.pb.setDisabled(True)
    self.textbox.textChanged.connect(self.disableButton)
    self.pb.clicked.connect(self.on_clicked_pb)
    self.clearbutton = QtWidgets.QPushButton(self.tr('Clear all'))
    self.clearbutton.setDisabled(True)
    self.clearbutton.clicked.connect(self.on_clicked_clear)

    vgroupbox = QtWidgets.QGroupBox('Options')
    pgroupbox = QtWidgets.QGroupBox('Partner')

    mainpanel = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.LeftToRight)
    variantpanel = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.TopToBottom)
    variantpanel.addWidget(self.variants)
    variantpanel.addWidget(self.textbox)
    variantpanel.addWidget(self.pb)
    variantpanel.addWidget(self.clearbutton)
    mainpanel.addWidget(pgroupbox)
    mainpanel.addWidget(vgroupbox)
    vgroupbox.setLayout(variantpanel)
    test = QtWidgets.QVBoxLayout(self)
    test.addLayout(self.pvbox)
    pgroupbox.setLayout(test)

    grid = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.TopToBottom, self)
    grid.addLayout(mainpanel)
    grid.addWidget(self.tablewidget)
    self.setLayout(grid)

def setCredentials(self, credentials): ################################
    self._credentials = credentials

def update_textbox(self, text):
    self.textbox.clear()
    textline = self.variants.itemText(text)
    self.textbox.setPlaceholderText(textline)
    if textline == 'IMEI':
        regexp = QtCore.QRegExp('^(?=.{0,16}$)(0\d+|[1-9][0-9]+)$')
    elif textline == 'PESEL':
        regexp = QtCore.QRegExp('^(?=.{0,11}$)(0\d+|[1-9][0-9]+)$')
    elif textline == 'NIP':
        regexp = QtCore.QRegExp('^(?=.{0,10}$)(0\d+|[1-9][0-9]+)$')
    elif textline == 'REGON':
        regexp = QtCore.QRegExp('^(?=.{0,9}$)(0\d+|[1-9][0-9]+)$')
    elif textline == 'Nazwisko':
        regexp = QtCore.QRegExp('[A-Za-zżźćńółęąśŻŹĆĄŚĘŁÓŃ]*')
    else:
        regexp = None
    self.textbox.setValidator(QtGui.QRegExpValidator(regexp))

@QtCore.pyqtSlot(QtWidgets.QAbstractButton)
@QtCore.pyqtSlot(int)
def on_itemSelected(self, index):
    if isinstance(index, QtWidgets.QAbstractButton):
        self.base = None
        element = '{}'.format(index.text())
        if element == 'Play':
            self.base = 'W2_FileImportWorkerP4'
        elif element == 'TMobile':
            self.base= 'W2_FileImportWorkerTmobileFIX'
        elif element == 'Orange':
            self.base = 'W2_FileImportWorkerOCP'
        elif element == 'PLK':
            self.base = 'W2_FileImportWorkerPLK'
        return self.base
    elif isinstance(index, int):
        pass

@QtCore.pyqtSlot()
def disableButton(self):
    val = bool(self.textbox.text())
    self.pb.setDisabled(not val)
    self.clearbutton.setDisabled(not val)

@QtCore.pyqtSlot()
def disablesql(self):
    self.textbox.setDisabled(True)
    self.pb.setDisabled(True)
    self.clearbutton.setDisabled(True)

@QtCore.pyqtSlot()
def enablesql(self):
    self.textbox.setDisabled(False)
    self.pb.setDisabled(False)
    self.clearbutton.setDisabled(False)


### run process button
@QtCore.pyqtSlot()
def on_clicked_pb(self):
    if self.textbox.text():
        threading.Thread(target=self.sql_query, daemon=True).start()

### clear all
@QtCore.pyqtSlot()
def on_clicked_clear(self):
    if self.textbox.text():
        self.textbox.clear()
    self.tablewidget.setRowCount(0)
    self.tablewidget.setColumnWidth(3, 200)

def table_performance(self):
    self.tablewidget.resizeColumnsToContents()
    self.tablewidget.setColumnWidth(4, 2500)
    self.tablewidget.setHorizontalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)

@QtCore.pyqtSlot(str, str)
def show_warning(self, title, msg):
    QtWidgets.QMessageBox.information(self, title, msg)

@QtCore.pyqtSlot(str, str)
def show_ok(self, title, msg):
    QtWidgets.QMessageBox.information(self, title ,msg)

@QtCore.pyqtSlot()
def clear_items(self):
    self.tablewidget.setRowCount(0)

@QtCore.pyqtSlot(int, int, str)
def add_item(self, row, column, val):
    if row >= self.tablewidget.rowCount():
        self.tablewidget.insertRow(self.tablewidget.rowCount())
    newitem = QtWidgets.QTableWidgetItem(val)
    self.tablewidget.setItem(row, column, newitem)

@QtCore.pyqtSlot()
def sort_items(self):
    self.tablewidget.sortItems(0, order=QtCore.Qt.DescendingOrder)

def sql_query(self):
    ser = '10.96.5.17\dqinstance'
    print(self.credentials) #check
    username, pwd = self._credentials ############################
    imei = '%' + self.textbox.text() + '%'
    self.clear_items()
    try:
        self.disablesql()
        connection = pyodbc.connect(driver='{SQL Server}', server=ser,
                                    user=username, password=pwd)
        if self.base == 'W2_FileImportWorkerTmobileFIX':
            cursor = connection.cursor()
            res = cursor.execute(''' 
                                                SELECT FI.FileNameOriginal,
                                                FI.OrderItemCode,
                                                FIR.Imported,
                                                FIRI.InfoCode,
                                                FR.Row
                                                FROM BIDQ_W2_DB.dbo.[FileImports] AS FI
                                    JOIN BIDQ_W2_DB.dbo.[FileImportRows] AS FIR ON FI.Id = FIR.FileImportId
                                    JOIN BIDQ_W2_DB.dbo.[FileRows] AS FR ON FIR.RowId = FR.RowId 
                                    LEFT JOIN BIDQ_W2_DB.dbo.FileImportRowInfoes AS FIRI ON FR.RowId = FIRI.RowId
                                                WHERE (FI.WorkerCode = ? or FI.WorkerCode = ?) and FR.Row LIKE ? ''',
                                 (self.base, self.base, imei))

        elif self.base == 'All':
            cursor = connection.cursor()
            res = cursor.execute(''' SELECT FI.FileNameOriginal,
                                    FI.OrderItemCode,
                                    FIR.Imported,
                                    FIRI.InfoCode,
                                    FR.Row
                                    FROM BIDQ_W2_DB.dbo.[FileImports] AS FI
                                    JOIN BIDQ_W2_DB.dbo.[FileImportRows] AS FIR ON FI.Id = FIR.FileImportId
                                    JOIN BIDQ_W2_DB.dbo.[FileRows] AS FR ON FIR.RowId = FR.RowId 
                                    LEFT JOIN BIDQ_W2_DB.dbo.FileImportRowInfoes AS FIRI ON FR.RowId = FIRI.RowId
                                    WHERE FR.Row LIKE ? ''',(imei))
        else:
            cursor = connection.cursor()
            res = cursor.execute('''
                                    SELECT FI.FileNameOriginal,
                                    FI.OrderItemCode,
                                    FIR.Imported,
                                    FIRI.InfoCode,
                                    FR.Row
                                    FROM BIDQ_W2_DB.dbo.[FileImports] AS FI
                                    JOIN BIDQ_W2_DB.dbo.[FileImportRows] AS FIR ON FI.Id = FIR.FileImportId
                                    JOIN BIDQ_W2_DB.dbo.[FileRows] AS FR ON FIR.RowId = FR.RowId 
                                    LEFT JOIN BIDQ_W2_DB.dbo.FileImportRowInfoes AS FIRI ON FR.RowId = FIRI.RowId
                                    WHERE FI.WorkerCode =  ? and FR.Row LIKE ? ''', (self.base, imei))

        if not cursor.rowcount:
            QtCore.QMetaObject.invokeMethod(self, 'show_warning',
                                            QtCore.Qt.QueuedConnection,
                                            QtCore.Q_ARG(str, 'IMEI'), QtCore.Q_ARG(str, 'No items found'))
        else:
            QtCore.QMetaObject.invokeMethod(self, 'clear_items', QtCore.Qt.QueuedConnection)
            QtCore.QThread.msleep(10)
            for row, form in enumerate(res):
                for column, item in enumerate(form):
                    QtCore.QMetaObject.invokeMethod(self, 'add_item',
                                                    QtCore.Qt.QueuedConnection,
                                                    QtCore.Q_ARG(int, row), QtCore.Q_ARG(int, column),
                                                    QtCore.Q_ARG(str, str(item)))
                    QtCore.QThread.msleep(10)
            QtCore.QMetaObject.invokeMethod(self, 'sort_items', QtCore.Qt.QueuedConnection)
            self.table_performance()
            QtCore.QMetaObject.invokeMethod(self, 'show_ok',
                                            QtCore.Qt.QueuedConnection,
                                            QtCore.Q_ARG(str, 'Done'), QtCore.Q_ARG(str, 'Items found'))
        cursor.close()

    except:
            QtCore.QMetaObject.invokeMethod(self, 'show_warning',
                                            QtCore.Qt.QueuedConnection,
                                            QtCore.Q_ARG(str, 'Error'), QtCore.Q_ARG(str, 'Something went wrong\n\n' \
                                                                                          'Contact [email protected]'))
    self.enablesql()

当我尝试从主要获取凭据 - 得到这样的错误:error

我试图将__main__中的凭据传递给Files()。怎么了?之前当我只有一个没有标签的主类时它起作用....在这种情况下传递凭证的最佳方法是什么?我问,因为即时通讯在其他选项卡中使用这些凭据。我应该仅为凭证创建子类吗?

# -- coding: utf-8 --

import sys
from PyQt5 import QtWidgets,QtGui
from QLogin import LoginDialog
from QApp import MainWindow
from QFilesTab import Files
import os


def resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
    return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath('.'), relative_path)


if __name__ == '__main__':

app = QtWidgets.QApplication(sys.argv)

login = LoginDialog()
login.setWindowIcon(QtGui.QIcon(resource_path('dc1.png')))

if login.exec_() != QtWidgets.QDialog.Accepted:
    sys.exit(-1)

files = Files()
window = MainWindow()
window.setWindowIcon(QtGui.QIcon(resource_path('dc1.png')))
window.setGeometry(500, 150, 800, 500)
files.setCredentials(login.credentials()) ###############################
window.show()
sys.exit(app.exec_())

在代码中我放了多个#################当我有问题的地方。

编辑:

登录对话框

# -- coding: utf-8 --

from PyQt5.QtWidgets import QLineEdit,QDialogButtonBox,QFormLayout,QDialog,QMessageBox
from PyQt5 import QtWidgets,QtCore
import qdarkstyle
import pyodbc


class LoginDialog(QDialog):
def __init__(self, parent=None):
    super(LoginDialog,self).__init__(parent)
    self.init_ui()


def init_ui(self):
    ### delete question mark
    self.setWindowFlags(self.windowFlags()
                        ^ QtCore.Qt.WindowContextHelpButtonHint)

    ### login & password fields
    self.username = QLineEdit(self)
    self.password = QLineEdit(self)
    self.password.setEchoMode(QLineEdit.Password)

    loginLayout = QFormLayout()
    loginLayout.addRow('Username', self.username)
    loginLayout.addRow('Password', self.password)
    self.buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
    self.buttons.accepted.connect(self.control)
    self.buttons.rejected.connect(self.reject)
    layout = QtWidgets.QVBoxLayout(self)
    layout.addLayout(loginLayout)
    layout.addWidget(self.buttons)
    self.setLayout(layout)

    ### set window title & stylesheet
    self.setWindowTitle('Villain - 10.96.6.14 ')
    #self.setWindowIcon(QtGui.QIcon('dc1.png'))
    self.setStyleSheet((qdarkstyle.load_stylesheet_pyqt5()))
    ###lock resize
    self.setSizeGripEnabled(False)
    self.setFixedSize(self.sizeHint())


def credentials(self):
    return self.username.text(), self.password.text()


###log by usins sql credentials
def control(self):
    ser = '10.96.5.17\dqinstance'
    login = self.username.text()
    pwd = self.password.text()

    try:
        self.connection = pyodbc.connect(driver='{SQL Server}', server=ser,
                     user=login, password=pwd)
        cursor = self.connection.cursor()
        cursor.close()
        self.accept()
    except:
        QMessageBox.warning(self, 'Error', 'Wrong username or password! \n\n'
                                           'Please use the SQL Server credentials ')
python pyqt pyqt5 qmainwindow
1个回答
0
投票

这就是我解决这个问题的方法:

  1. 在Main.py中,我已经将LoginDIalog类的参数传递给MainWindow类。 window.tab_layout(login.credentials())
  2. 在QApp.py中,我编辑了方法tab_layout: def tab_layout(self, credentials): self.tabwidget = QtWidgets.QTabWidget() self.tabwidget.addTab(Files(credentials), 'Files Import') self.tabwidget.addTab(Webservices(), 'Webservice') self.setCentralWidget(self.tabwidget)
  3. 在QFilesTab.py中,我添加了Files类constuctor self._credentials = credentials和删除方法setCredentials。现在,我的sql_query方法正在使用来自constuctor的凭据。
© www.soinside.com 2019 - 2024. All rights reserved.