3

I am trying to find open ports and add them to my menu. Right now, what I succeed having an action to my menu (like, "find ports"), and only if it's clicked - it will connect to my function that gets all free ports. Unfortunately, that's not what I am looking for.

I want to click on the menu title, and get all port in my menu. Below is the code I have:

This is the GUI part:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(150, 150)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.portList = QtWidgets.QPushButton(self.centralwidget)
        self.portList.setGeometry(QtCore.QRect(10, 50, 65, 23))
        self.portList.setObjectName("portList")

        self.productMenu=QtWidgets.QMenu(self.centralwidget)
#        self.productMenu.addAction("Find Port") <-------- If I add this, then it works when I click on "Find Port"

        self.portList.setMenu(self.productMenu)

        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)





    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "GUI"))
        self.portList.setText(_translate("MainWindow", "Ports"))

And this is where I run my functions:

from PyQt5 import QtWidgets, QtCore, QtGui
from test1 import Ui_MainWindow
import serial.tools.list_ports
import sys

class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(ApplicationWindow, self).__init__()

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.productMenu.triggered.connect(self.findPort)

        self.ui.portList.clicked.connect(self.findPort)
        ###I tried both lines above, but it doesn't connect to the function###
    def findPort(self):
          comPorts = list(serial.tools.list_ports.comports())
          print("clicked!")
           for counter in comPorts:
               strPort=str(counter)
               print(strPort)
               self.ui.productMenu.addAction(strPort)

    def portClick(self,action):
        print(action.text())


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    application = ApplicationWindow()
    application.show()
    sys.exit(app.exec_())

How can I get the findport function to connect by pressing the title of the menu, and get it updated immediately with the free ports?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Alon123
  • 164
  • 3
  • 15

1 Answers1

4

You have to use the aboutToShow signal:

self.ui.productMenu.aboutToShow.connect(self.findPort)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks! it works! but I am having a different problem now: when I click on it it keeps adding ports, even if the port has been added before. Is there a way to prevent it? Like if I clicked on it once, and port COM1 has appeared, what can I do to prevent COM1 from appearing multiple times, even if I click on the button a few times? – Alon123 Feb 09 '20 at 12:47
  • 1
    @Alon123 It is understood that you want to show the available ports then clean the QActions before adding the new ones: `self.ui.productMenu.clear()` `for portname in serial.tools.list_ports.comports():` `self.ui.productMenu.addAction(str(portname))` – eyllanesc Feb 09 '20 at 12:52