Python Forum
event driven coding PyQt6 on Combobox change
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
event driven coding PyQt6 on Combobox change
#1
I have the working code below running in a venv using python 3.7.6 what I want is when the Province combobox is changed have the stations combobox updated with that selected Provinces stations. How do I hook that event?



import sys
from PyQt6 import QtGui, QtCore
import bs4
from bs4 import BeautifulSoup
import requests
#import urllib3 as urllib # the lib that handles the url stuff
import urllib.request


provs = ['AB','BC','MB','NB','NL','NS','NT','NU','ON','PE','QC','SK','YT']
for prov in provs:
    print(prov)
    url = 'https://dd.weather.gc.ca/hydrometric/csv/' + prov + '/daily/' + prov + '_daily_hydrometric.csv'
    print(url)

#https://dd.weather.gc.ca/hydrometric/doc/hydrometric_StationList.csv
def getStationsProv(provis):
      data = urllib.request.urlopen('https://dd.weather.gc.ca/hydrometric/doc/hydrometric_StationList.csv') # it's a file like object and works just like a file
      dataFiltered = []
      for line in data: # files are iterable
          #print(line.decode())
          data = line.decode().split(",")
#          dataFiltered.append("Station1")
          if  data[4] == provis : 
              arrayData = str(data[0]) + '-' + str(data[1]).replace('"','').replace(' ','_')
              dataFiltered.append(arrayData)
#              print(arrayData)
#      print(dataFiltered)
#      dataFiltered.append("Station2")
      return dataFiltered
	
import sys

from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (
    QApplication,
    QCheckBox,
    QComboBox,
    QDateEdit,
    QDateTimeEdit,
    QDial,
    QDoubleSpinBox,
    QFontComboBox,
    QLabel,
    QLCDNumber,
    QLineEdit,
    QMainWindow,
    QProgressBar,
    QPushButton,
    QRadioButton,
    QSlider,
    QSpinBox,
    QTimeEdit,
    QVBoxLayout,
    QWidget,
)


# Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow):


    def getValue(self):
        provIs = self.cbUser.itemData(self.qcb1.currentIndex()).toPyObject()
        print(str(id_us))

    def __init__(self):
        super().__init__()

        self.setWindowTitle("Env Canada hydrometric data")
        self.setFixedWidth(500)
        layout = QVBoxLayout()
		
        label1 = QLabel("Select a province") #,
        layout.addWidget(label1)
		
        qcb1 = QComboBox() #,
        qcb1.addItems(provs)
        layout.addWidget(qcb1)
		
        qcb2 = QComboBox()
        df = getStationsProv(qcb1.currentText())
        #df = getStationsProv('AB')
        #print(df)
        qcb2.addItems(df)
        layout.addWidget(qcb2)
		
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)


app = QApplication(sys.argv)
window = MainWindow()
window.show()

app.exec()

Attached Files

.py   HTTPListerProvincialQTEnv.py (Size: 2.54 KB / Downloads: 113)
Reply
#2
You can connect QComboBox.currentIndexChanged() to the function

import sys
 
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (
    QApplication,
    QCheckBox,
    QComboBox,
    QDateEdit,
    QDateTimeEdit,
    QDial,
    QDoubleSpinBox,
    QFontComboBox,
    QLabel,
    QLCDNumber,
    QLineEdit,
    QMainWindow,
    QProgressBar,
    QPushButton,
    QRadioButton,
    QSlider,
    QSpinBox,
    QTimeEdit,
    QVBoxLayout,
    QWidget,
)
import bs4
from bs4 import BeautifulSoup
import requests
#import urllib3 as urllib # the lib that handles the url stuff
import urllib.request
 
 
provs = ['AB','BC','MB','NB','NL','NS','NT','NU','ON','PE','QC','SK','YT']
for prov in provs:
    print(prov)
    url = 'https://dd.weather.gc.ca/hydrometric/csv/' + prov + '/daily/' + prov + '_daily_hydrometric.csv'
    print(url)
 
#https://dd.weather.gc.ca/hydrometric/doc/hydrometric_StationList.csv
def getStationsProv(provis):
      data = urllib.request.urlopen('https://dd.weather.gc.ca/hydrometric/doc/hydrometric_StationList.csv') # it's a file like object and works just like a file
      dataFiltered = []
      for line in data: # files are iterable
          #print(line.decode())
          data = line.decode().split(",")
#          dataFiltered.append("Station1")
          if  data[4] == provis : 
              arrayData = str(data[0]) + '-' + str(data[1]).replace('"','').replace(' ','_')
              dataFiltered.append(arrayData)
#              print(arrayData)
#      print(dataFiltered)
#      dataFiltered.append("Station2")
      return dataFiltered
     

 
 
# Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow):
 
 
    def getValue(self):
        provIs = self.cbUser.itemData(self.qcb1.currentIndex()).toPyObject()
        print(str(id_us))
 
    def __init__(self):
        super().__init__()
 
        self.setWindowTitle("Env Canada hydrometric data")
        self.setFixedWidth(500)
        layout = QVBoxLayout()
         
        label1 = QLabel("Select a province") #,
        layout.addWidget(label1)
         
        self.qcb1 = QComboBox() #,
        self.qcb1.addItems(provs)
        self.qcb1.currentIndexChanged.connect(self.qcb1_index_changed)
        layout.addWidget(self.qcb1)
         
        self.qcb2 = QComboBox()
        layout.addWidget(self.qcb2)
         
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        self.qcb1_index_changed()
        
        
    def qcb1_index_changed(self):
        self.qcb2.clear()
        print("qcb1_index_changed")
        df = getStationsProv(self.qcb1.currentText())
        self.qcb2.addItems(df)
        
 
 
app = QApplication(sys.argv)
window = MainWindow()
window.show()
 
app.exec()
Reply
#3
I would write like this:
import sys
from PyQt5 import QtWidgets
import urllib.request

provinces = ("AB", "BC", "MB", "NB", "NL", "NS", "NT", "NU", "ON", "PE", "QC", "SK", "YT")
province_station_url = (
    "https://dd.weather.gc.ca/hydrometric/doc/hydrometric_StationList.csv"
)


class MainWindow(QtWidgets.QMainWindow):
    """Demonstrate QComboBox.currentIndexChanged."""
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Env Canada hydrometric data")
        center = QtWidgets.QWidget(self)
        self.setCentralWidget(center)
        layout = QtWidgets.QVBoxLayout(center)
        label = QtWidgets.QLabel("Select a province", center)
        layout.addWidget(label)
        self.province = QtWidgets.QComboBox(center)
        self.province.addItems(provinces)
        layout.addWidget(self.province)
        self.stations = QtWidgets.QComboBox(center)
        layout.addWidget(self.stations)
        # Update station list when province changes
        self.province.currentIndexChanged.connect(self.update_stations)
        self.update_stations()

    def update_stations(self):
        """Update station list based on selected province."""
        self.stations.clear()
        province = self.province.currentText()
        for line in urllib.request.urlopen(province_station_url):
            info = line.decode().strip().split(",")
            # To prevent an index error, check length first
            if len(info) >= 5 and info[4] == province:
                self.stations.addItem(f"""{info[1].replace('"', '').replace(' ', '_')}""")


app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()

app.exec()
Notes:
Generally, I prefer to import packages and use the package name to help identify where I am getting classes or functions. For Qt this means I prefer this:
import sys
from PyQt5 import QtWidgets
...
app = QtWidgets.QApplication(sys.argv)
to this:
from sys import argv
from PyQt5.QtWidgets import QApplication
...
app = QApplication(argv)
I don't know if this happens on other platforms, but on Windows I used to have a problem with widgets popping up as windows on the screen when the application started only to disappear before the main window was drawn. This does not happen when I specify the parent when I create a widget instead of waiting for the layout manager to do so. That is why you see this in my code:
        center = QtWidgets.QWidget(self)  # make the center widget as a child of the MainWindow
        self.setCentralWidget(center)
        layout = QtWidgets.QVBoxLayout(center)
        label = QtWidgets.QLabel("Select a province", center)   # When making widgets, specify the parent
I do not know if this happens on other operating systems.
Reply
#4
Hey That works perfectly

Thanks Axel!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyQt] Saving file to html or pdf stopped working in PyQt6 ejKDE 4 278 Mar-12-2024, 07:45 PM
Last Post: ejKDE
  [PyQt] [solved] How to display a pdf-file in a PyQt6 widget BigMan 13 15,700 May-06-2023, 09:27 AM
Last Post: Axel_Erfurt
Question [PyQt] Application desktop toolbar with PyQt6 bunz 4 1,455 Mar-09-2023, 08:09 PM
Last Post: bunz
  PyQt6 QAction with icon and string malonn 2 1,620 Sep-12-2022, 11:59 AM
Last Post: malonn
  [PyQt] How can I sync Combobox index to other combobox index? nickzsche 2 2,336 Jan-03-2022, 12:29 PM
Last Post: Axel_Erfurt
  [PyQt] Embed Google Maps in PyQt6 Widget Raures 2 3,038 Sep-11-2021, 04:32 PM
Last Post: Raures
  [PyQt] Help: Replace widgets in a QFrame on Combobox change mart79 2 3,440 May-14-2020, 05:21 AM
Last Post: mart79

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020