如何更新一个组合框的内容,具体取决于在PyQt5中另一个组合框中选择的值

时间:2019-03-02 20:39:09

标签: python pyqt pyqt5

我的代码如下:

medi_colab.db的提取代码:

from collections import OrderedDict
import pandas as pd
import numpy as np
import sqlite3

pd.set_option('display.max_columns', 5)

df = pd.read_csv('icd_codes_final.csv')
#print(df[['icd_code', 'common_name']].head(20))

#generate unique icd codes and the common names associated with them
#convert to lists
icd_codes = df['icd_code'].values.tolist()
common_names = df['common_name'].values.tolist()

#Remove duplicates while preserving order
icd_codes = list(sorted(OrderedDict.fromkeys(icd_codes)))
common_names = list(OrderedDict.fromkeys(common_names))

mapping = list(zip(icd_codes, common_names))
print("{} {}".format(type(mapping[0][0]), type(mapping[0][1])))
#for icd_code, common_name in mapping:
    #print("{} {}".format(icd_code, common_name))

#create offline sqlite3 database
conn = sqlite3.connect('medi_colab.db')

#create a cursor
c = conn.cursor()

#create icd_codes table
c.execute("""CREATE TABLE icd_codes (icd_code VARCHAR(10) PRIMARY KEY, 
common_name VARCHAR(50) NOT NULL)""")

#commit changes to the database
conn.commit()

#insert mapped list rows one by one
for icd_code, common_name in mapping:
    c.execute("INSERT INTO icd_codes (icd_code, common_name) VALUES 
    (?, ?)", (icd_code, common_name))

conn.commit()

#extract contents for the icd_sub_codes table
df = df[['icd_sub_code', 'scientific_name', 'icd_code']]

#create icd_sub_codes table
c.execute("""CREATE TABLE icd_sub_codes 
        (icd_sub_code VARCHAR(10) PRIMARY KEY, 
        scientific_name TEXT,
        icd_code VARCHAR(50), 
        FOREIGN KEY(icd_code) REFERENCES icd_codes(icd_code))""")

#append the rows to the table
df.to_sql('icd_sub_codes', con = conn, if_exists = 'append', index = 
False)
conn.commit()
print("TABLE icd_sub_codes has been successfully populated")

autocomplete.py:

import sqlite3, os
path = '/.../MedRec/'
class DiseaseList:
    def __init__(self):
        self.conn = sqlite3.connect(path + 'databases/medi_colab.db')
        self.c = self.conn.cursor()

    def generate_common_names_list(self):
        #accept common names output column from DB
        self.c.execute("""SELECT * FROM icd_codes""")
        names = self.c.fetchall()    #get output tuples
        common_names = ['']   #initialize a list with an empty string

        #extract common names from output tuples into a list
        for common_name in names:
            name = common_name[0] + ' - ' + common_name[1]
            common_names.append(name)

        return common_names

    def generate_scientific_names_list(self, icd_code):
        #get icd_sub_code and sub disease name from common name
        self.c.execute("""SELECT * FROM icd_sub_codes WHERE icd_code = 
        '{}'""".format(icd_code))
        return self.c.fetchall()

autocompletecombo.py:

import sys
from PyQt5.QtWidgets import QComboBox, QCompleter, QApplication, 
QWidget
from PyQt5.QtCore import QSortFilterProxyModel, Qt 

class autocompleteGUI(QComboBox):
    def __init__(self, parent = None):
        super(autocompleteGUI, self).__init__(parent)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setEditable(True)

        # add a filter model to filter matching items
        self.pFilterModel = QSortFilterProxyModel(self)
        self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.pFilterModel.setSourceModel(self.model())

        # add a completer, which uses the filter model
        self.completer = QCompleter(self.pFilterModel, self)

        # always show all (filtered) completions
self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
        self.setCompleter(self.completer)
        self.resize(700, 30)

        # connect signals
        def filter(text):
            self.pFilterModel.setFilterFixedString(str(text))

    self.lineEdit().textEdited.connect(filter)
    self.completer.activated.connect(self.on_completer_activated)
    # on selection of an item from the completer, select the 
    corresponding item from combobox
    def on_completer_activated(self, text):
        if text:
            index = self.findText(str(text))
            self.setCurrentIndex(index)

dropdown.py:

from PyQt5.QtWidgets import QComboBox
class dropdownMenu(QComboBox):
    def __init__(self, parent = None):
        super(dropdownMenu, self).__init__(parent)
        self.resize(700, 30)
        self.show()

formwindow.py:

import sys
path = '/.../MedRec'
sys.path.append(path + '/data/')
sys.path.append(path + '/GUI/')
from autocomplete import DiseaseList
from autocompletecombo import autocompleteGUI
from dropdown import dropdownMenu
from PyQt5.QtWidgets import QMainWindow

class formwindowGUI(QMainWindow):
    def __init__(self, parent = None):
        super(formwindowGUI, self).__init__(parent)
        self.common_names = []
        self.scientific_names = []
        self.dl = DiseaseList()
        self.initUI()

    def initUI(self):
        ac = autocompleteGUI(self)
        dm = dropdownMenu(self)

        #add common names to autocomplete GUI
        self.common_names = self.dl.generate_common_names_list()
        ac.addItems(self.common_names)
        self.setGeometry(150, 150, 1080, 720)
        ac.move(20, 50)
        dm.move(20, 90)
        self.show()

        ac.activated.connect(self.initialize_subdisease_list)

        #connect to generate_scientific_diseases_list in 
        #data.autocomplete.DiseaseList
    def initialize_subdisease_list(self, index):

        #reference disease name by index
        common_name = self.common_names[index]

        #retrieve ICD Code
        icd_code = common_name.split(' ')[0]

        #if list is not empty, remove all contents
        if not (not self.scientific_names):
            del self.scientific_names[:]

        temp = self.dl.generate_scientific_names_list(icd_code)
        for item in temp:
            final = item[0] + ' - ' + item[1] + ' - ' + item[2]
            self.scientific_names.append(final)

       print(self.scientific_names)
       #dm.addItems(self.scientific_names)

我希望在运行时在autocompleteGUI小部件的项目列表中选择一个项目时,使用在initialize_subdisease_list()函数中生成的科学名称列表中的值填充dropdownMenu类实例dm。

我已经尝试了以下方法:

class formwindowGUI(QMainWindow):
    def __init__(self, parent = None):
        super(formwindowGUI, self).__init__(parent)
        self.ac = autocompleteGUI()
        self.dm = dropdownMenu()

这将导致两个单独的GUI窗口,其中自动完成组合框与主窗口GUI分开显示,并且根本不起作用。

有人可以建议我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

可以使用QSqlQueryModel来代替使您复杂的逻辑,

from PyQt5 import QtCore, QtGui, QtWidgets, QtSql

def createConnection():
    db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
    db.setDatabaseName('medi_colab.db')
    if not db.open():
        QtWidgets.QMessageBox.critical(None, QtWidgets.qApp.tr("Cannot open database"),
                             QtWidgets.qApp.tr("Unable to establish a database connection.\n"
                                     "This example needs SQLite support. Please read "
                                     "the Qt SQL driver documentation for information "
                                     "how to build it.\n\n"
                                     "Click Cancel to exit."),
                             QtWidgets.QMessageBox.Cancel)
        return False
    return True

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        combo_icd_codes = QtWidgets.QComboBox()
        self.model_ics_codes = QtSql.QSqlQueryModel(self)
        combo_icd_codes.setModel(self.model_ics_codes)

        self.combo_icd_sub_codes = QtWidgets.QComboBox()
        self.model_ics_sub_codes = QtSql.QSqlQueryModel(self)
        self.combo_icd_sub_codes.setModel(self.model_ics_sub_codes)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QGridLayout(central_widget)
        lay.addWidget(combo_icd_codes, 0, 0)
        lay.addWidget(self.combo_icd_sub_codes, 0, 1)
        lay.setRowStretch(1, 1)

        combo_icd_codes.currentIndexChanged[int].connect(self.on_currentIndexChanged)
        query = QtSql.QSqlQuery('''SELECT icd_code || ' ' || common_name AS string_join, icd_code 
            FROM icd_codes''')
        query.exec_()
        self.model_ics_codes.setQuery(query)
        combo_icd_codes.setCurrentIndex(0)

    @QtCore.pyqtSlot(int)
    def on_currentIndexChanged(self, index):
        ix = self.model_ics_codes.index(index, 1)
        icd_sub_code = self.model_ics_codes.data(ix)
        query = QtSql.QSqlQuery('''SELECT icd_sub_code || ' ' || scientific_name || ' ' || icd_code AS string_join 
            FROM icd_sub_codes 
            WHERE icd_code = ?''')
        query.addBindValue(icd_sub_code)
        query.exec_()
        self.model_ics_sub_codes.setQuery(query)
        self.combo_icd_sub_codes.setCurrentIndex(0)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    if not createConnection():
        sys.exit(-1)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())