Python Forum

Full Version: Simple printing the text for a QLineEdit
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
I'm simply trying to print whatever the user has typed in the QLineEdit named self.snTextBox using the QPushButton called self.cfButton. I tried using str for both but it makes no difference. What do I need to do here? The self.enButton works calling the function enterNewHardware.

App won't even run with the below.


I'm getting this error:
Error:
self.cfButton.clicked.connect(print(serialNumber)) TypeError: argument 1 has unexpected type 'NoneType'
class hardwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snLabel = QLabel("SERIAL NUMBER")
        self.snTextBox = QLineEdit()
        self.modelLabel = QLabel("MODEL")
        self.modelTextBox = QLineEdit()
        self.userLabel = QLabel("USER")
        self.userTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW HARDWARE")
        self.cfButton = QPushButton("CLEAR FIELDS")
        self.seButton = QPushButton("SEARCH/EDIT HARDWARE")
        self.activeCheckbox = QCheckBox("ACTIVE")

        layout = QVBoxLayout(self)
        layout.addWidget(self.snLabel)
        layout.addWidget(self.snTextBox)
        layout.addWidget(self.modelLabel)
        layout.addWidget(self.modelTextBox)
        layout.addWidget(self.userLabel)
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.activeCheckbox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)

        self.enButton.clicked.connect(enterNewHardware)

        serialNumber = self.snTextBox.text()
        self.cfButton.clicked.connect(print(serialNumber))
This:
self.cfButton.clicked.connect(print(serialNumber))
calls the print function and connects "clicked" to the return value, which is None. You need to connect "clicked" to a function, not a function call. This would work.
def print_serialnumber():
    print(self.snTextBox.text())
...
self.cfButton.clicked.connect(print_serialnumber)
If you don't want to write a function, you can use a lambda expression, essentially an in-line function.
self.cfButton.clicked.connect(lambda: print(self.snTextBox.text())
In the future please provide enough of an example that others can run the code.

And for widgets that you will never reference, there is no need to keep a reference in your class. Will you ever use snLabel, modelLabel or userLabel?
        layout = QVBoxLayout(self)
        layout.addWidget(QLabel("SERIAL NUMBER"))
        layout.addWidget(self.snTextBox)
        layout.addWidget(QLabel("MODEL"))
        layout.addWidget(self.modelTextBox)
        layout.addWidget(QLabel("USER"))
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.activeCheckbox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)
So here is my all the code. Pretty much setup testing calling a function via button click and testing db connection which works. The code is working but of course the button is just inserting hard-coded data.

Line 47 self.enButton.clicked.connect(enterNewHardware)

I need to pass whatever the user enters in snTextBox, modelTextBox, userTextBox and activeCheckbox and pass it to the function enterNewHardware to insert the data into my database. Can't use a global variable here. Tried turning function enterNewHardware into a class which would inherit the hardwareTab class but hit the wall there too. Feel like this is so easy and for whatever reason I'm blanking.


from PyQt5.QtWidgets import (QLabel, QPushButton, QLineEdit, QApplication, QCheckBox, QMainWindow, QWidget,
                             QVBoxLayout, QTabWidget, QStatusBar)
import pyodbc
import sys


class mainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(385, 323)
        self.setWindowTitle("HARDWARE | SOFTWARE MANAGER")
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)

        self.tabForm = QTabWidget()
        self.tabForm.addTab(hardwareTab(), "HARDWARE")
        self.tabForm.addTab(softwareTab(), "SOFTWARE")
        self.setCentralWidget(self.tabForm)


class hardwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snLabel = QLabel("SERIAL NUMBER")
        self.snTextBox = QLineEdit()
        self.modelLabel = QLabel("MODEL")
        self.modelTextBox = QLineEdit()
        self.userLabel = QLabel("USER")
        self.userTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW HARDWARE")
        self.cfButton = QPushButton("CLEAR FIELDS")
        self.seButton = QPushButton("SEARCH/EDIT HARDWARE")
        self.activeCheckbox = QCheckBox("ACTIVE")

        layout = QVBoxLayout(self)
        layout.addWidget(self.snLabel)
        layout.addWidget(self.snTextBox)
        layout.addWidget(self.modelLabel)
        layout.addWidget(self.modelTextBox)
        layout.addWidget(self.userLabel)
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.activeCheckbox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)

        self.enButton.clicked.connect(enterNewHardware)


class softwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snLabel = QLabel("SERIAL NUMBER / KEY")
        self.snTextbox = QLineEdit()
        self.nameLabel = QLabel("APPLICATION NAME")
        self.nameTextBox = QLineEdit()
        self.userLabel = QLabel("USER")
        self.userTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW SOFTWARE")
        self.cfButton = QPushButton("CLEAR FIELDS")
        self.seButton = QPushButton("SEARCH/EDIT SOFTWARE")

        layout = QVBoxLayout(self)
        layout.addWidget(self.snLabel)
        layout.addWidget(self.snTextbox)
        layout.addWidget(self.nameLabel)
        layout.addWidget(self.nameTextBox)
        layout.addWidget(self.userLabel)
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)


def enterNewHardware():
    azureServer = "pythonserver5874.database.windows.net"
    azureDB = "inventoryDatabase"
    userName = "na"
    password = "na"
    driver = "{ODBC Driver 17 for SQL Server}"
    connectionString = f"DRIVER={driver};SERVER={azureServer};PORT=1433;DATABASE={azureDB};UID={userName};PWD={password}"
    conn = pyodbc.connect(connectionString)
    sqlCMD = conn.cursor()

    sqlCMD.execute('SELECT * FROM inventoryDatabase.dbo.Hardware')
    sqlCMD.execute('''
                    INSERT INTO inventoryDatabase.dbo.Hardware(serialNumber, modelName, userName, machineActive)
                    VALUES
                    ('J69745', 'L7410', 'CMULLEN', 'True')
                    ''')
    conn.commit()


if __name__ == "__main__":
    APP = QApplication(sys.argv)
    WINDOW = mainWindow()
    WINDOW.show()
    sys.exit(APP.exec_())
Turned enterNewHardware into a class and inherited the hardwareTab class. Able to assign the textboxes to variables but unable to reference them in the sql statement now. Program runs but when you click the enter hardware button it processes for a second and closes out and doesn't do anything.

from PyQt5.QtWidgets import (QLabel, QPushButton, QLineEdit, QApplication, QCheckBox, QMainWindow, QWidget,
                             QVBoxLayout, QTabWidget, QStatusBar)
import pyodbc
import sys


class mainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(385, 323)
        self.setWindowTitle("HARDWARE | SOFTWARE MANAGER")
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)

        self.tabForm = QTabWidget()
        self.tabForm.addTab(hardwareTab(), "HARDWARE")
        self.tabForm.addTab(softwareTab(), "SOFTWARE")
        self.setCentralWidget(self.tabForm)


class hardwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snLabel = QLabel("SERIAL NUMBER")
        self.snTextBox = QLineEdit()
        self.modelLabel = QLabel("MODEL")
        self.modelTextBox = QLineEdit()
        self.userLabel = QLabel("USER")
        self.userTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW HARDWARE")
        self.cfButton = QPushButton("CLEAR FIELDS")
        self.seButton = QPushButton("SEARCH/EDIT HARDWARE")
        self.activeCheckbox = QCheckBox("ACTIVE")

        layout = QVBoxLayout(self)
        layout.addWidget(self.snLabel)
        layout.addWidget(self.snTextBox)
        layout.addWidget(self.modelLabel)
        layout.addWidget(self.modelTextBox)
        layout.addWidget(self.userLabel)
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.activeCheckbox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)

        self.enButton.clicked.connect(enterNewHardware)


class softwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snLabel = QLabel("SERIAL NUMBER / KEY")
        self.snTextbox = QLineEdit()
        self.nameLabel = QLabel("APPLICATION NAME")
        self.nameTextBox = QLineEdit()
        self.userLabel = QLabel("USER")
        self.userTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW SOFTWARE")
        self.cfButton = QPushButton("CLEAR FIELDS")
        self.seButton = QPushButton("SEARCH/EDIT SOFTWARE")

        layout = QVBoxLayout(self)
        layout.addWidget(self.snLabel)
        layout.addWidget(self.snTextbox)
        layout.addWidget(self.nameLabel)
        layout.addWidget(self.nameTextBox)
        layout.addWidget(self.userLabel)
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)


class enterNewHardware(hardwareTab):
    def __init__(self):
        super().__init__()

        serial_number = self.snTextBox.text()
        model_name = self.modelTextBox.text()
        user_name = self.userTextBox.text()
        active_machine = self.activeCheckbox.setChecked()

        azureServer = "pythonserver5874.database.windows.net"
        azureDB = "inventoryDatabase"
        userName = "na"
        password = "na"
        driver = "{ODBC Driver 17 for SQL Server}"
        connectionString = f"DRIVER={driver};SERVER={azureServer};PORT=1433;DATABASE={azureDB};UID={userName};PWD={password}"
        conn = pyodbc.connect(connectionString)
        sqlCMD = conn.cursor()

        sqlCMD.execute('SELECT * FROM inventoryDatabase.dbo.Hardware')
        sqlCMD.execute('''
                        INSERT INTO inventoryDatabase.dbo.Hardware(serialNumber, modelName, userName, machineActive)
                        VALUES
                        (serial_number, model_name, user_name, active_machine)
                        ''')
        conn.commit()


if __name__ == "__main__":
    APP = QApplication(sys.argv)
    WINDOW = mainWindow()
    WINDOW.show()
    sys.exit(APP.exec_())
You could use WINDOW.tab_form.currentWidget() to get the selected widget (either a hardwareTab or softwareTab). You can use this to get hold of any of the parts. Once you have the parts you can get the text you need.

Subclassing enterNewHardware from hardwareTab does not do what you want. enterNewHardware() creates a new enterNewHardware object. This object has no visibility into your existing hardwareTab object. It has the same attirbute names, but the objects in the hardwareTab object are completely different than the enterNewHardware objects. The two things are similar types, but not the same thing. You and I are People, but I don't know how much change is in your pocket.

You could do something like this:
class mainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.tabForm = QTabWidget()
        self.tabForm.addTab(hardwareTab(), "HARDWARE")
        self.setCentralWidget(self.tabForm)

class hardwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW HARDWARE")
 
        layout = QVBoxLayout(self)
        layout.addWidget(self.snTextBox)
        layout.addWidget(self.enButton)
 
        self.enButton.clicked.connect(lambda: enterNewHardware(self))
 
def enterNewHardware(hardware):
    serial_number = hardware.snTextBox.text()
...
    conn.commit()

if __name__ == "__main__":
    APP = QApplication(sys.argv)
    WINDOW = mainWindow()
    WINDOW.show()
    sys.exit(APP.exec_())
Here we pass the hardwareTab object as an argument to the enterNewHardware() function. This object contains the widgets you are looking for.

It might make more sense to make "enterNewHardware()" a method of hardwareTab. Or it might make more sense to make it a "glue" function that knows enough about hardwareTab and enough about the database to serve as an intermediary.
Going to try both options tonight. What do you mean by "glue" function?
Glue code is a bit of code that ties two things together. In your example you might have a database object and a tab page object. Ideally the tab page shouldn't have to know anything about the database, or the database know anything about the tab page. To make the two parts work together you write a little bit of code that knows just enough about both pieces to "glue" them together and do something.

The glue code can be quite substantial and given fancy names. In the MVVM design pattern the Model would be your database. The View your tab page. And the View Model is the glue code that gets info from the tab page and modifies the database. You were attempting to make a View Model (glue) when you wrote the enterNewHardware class.
Unfortunately neither way works. Tried the lambda function and added the hardwareTab class as an argument in the enterNewHardware function but still unable to reference the textbox variables in the SQL statement. Same deal when placing the enterNewHardware() function under the hardwareTab class. The app runs with the code both ways but when you click the Enter New Hardware button it spins for a second and then just closes out with no error messages.

Damnit what am I missing. I feel like I have tried every way possible. The syntax for calling the textbox variables in the SQL statement isn't incorrect is it? The instances of the textbox variables stays grayed out as if they aren't being called at all in the SQL statement.
I think the issue is my SQL statement. I went back and made the enterNewHardware function into a class and inherited the hardwareTab class. I feel this has been the closest way so far because I have access to both the text boxes and database this way. I have gotten to the point now where my variables are being referenced in the SQL statement(no longer grayed out)....still clicking the button makes the cursor spin for a second, app exits and no data entered. I took out the SELECT statement because I don't see why it would be needed. I got the original sql statement from microsoft to test the connection to the database.

from PyQt5.QtWidgets import (QLabel, QPushButton, QLineEdit, QApplication, QCheckBox, QMainWindow, QWidget,
                             QVBoxLayout, QTabWidget, QStatusBar)
import pyodbc
import sys


class mainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(385, 323)
        self.setWindowTitle("HARDWARE | SOFTWARE MANAGER")
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)

        self.tabForm = QTabWidget()
        self.tabForm.addTab(hardwareTab(), "HARDWARE")
        self.tabForm.addTab(softwareTab(), "SOFTWARE")
        self.setCentralWidget(self.tabForm)


class hardwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snLabel = QLabel("SERIAL NUMBER")
        self.snTextBox = QLineEdit()
        self.modelLabel = QLabel("MODEL")
        self.modelTextBox = QLineEdit()
        self.userLabel = QLabel("USER")
        self.userTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW HARDWARE")
        self.cfButton = QPushButton("CLEAR FIELDS")
        self.seButton = QPushButton("SEARCH/EDIT HARDWARE")
        self.activeCheckbox = QCheckBox("ACTIVE")

        layout = QVBoxLayout(self)
        layout.addWidget(self.snLabel)
        layout.addWidget(self.snTextBox)
        layout.addWidget(self.modelLabel)
        layout.addWidget(self.modelTextBox)
        layout.addWidget(self.userLabel)
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.activeCheckbox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)

        self.enButton.clicked.connect(enterNewHardware)


class softwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snLabel = QLabel("SERIAL NUMBER / KEY")
        self.snTextbox = QLineEdit()
        self.nameLabel = QLabel("APPLICATION NAME")
        self.nameTextBox = QLineEdit()
        self.userLabel = QLabel("USER")
        self.userTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW SOFTWARE")
        self.cfButton = QPushButton("CLEAR FIELDS")
        self.seButton = QPushButton("SEARCH/EDIT SOFTWARE")

        layout = QVBoxLayout(self)
        layout.addWidget(self.snLabel)
        layout.addWidget(self.snTextbox)
        layout.addWidget(self.nameLabel)
        layout.addWidget(self.nameTextBox)
        layout.addWidget(self.userLabel)
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)


class enterNewHardware(hardwareTab):
    def __init__(self):
        super().__init__()

        serial_number = self.snTextBox.text()
        model_name = self.modelTextBox.text()
        user_name = self.userTextBox.text()
        active_machine = self.activeCheckbox.setChecked()

        azureServer = "pythonserver5874.database.windows.net"
        azureDB = "inventoryDatabase"
        userName = "na"
        password = "na"
        driver = "{ODBC Driver 17 for SQL Server}"
        connectionString = f"DRIVER={driver};SERVER={azureServer};PORT=1433;DATABASE={azureDB};UID={userName};PWD={password}"
        conn = pyodbc.connect(connectionString)

        cursor = conn.cursor()
        cursor.execute("INSERT INTO inventoryDatabase.dbo.Hardware VALUES (%s, %s, %s, %s)", (serial_number, model_name, user_name, active_machine))
        conn.commit()

        #sqlCMD.execute('SELECT * FROM inventoryDatabase.dbo.Hardware')
        #sqlCMD.execute('''
                        #INSERT INTO inventoryDatabase.dbo.Hardware(serialNumber, modelName, userName, machineActive)
                        #VALUES
                        #(serial_number, model_name, user_name, active_machine)
                        #''')
        #conn.commit()


if __name__ == "__main__":
    APP = QApplication(sys.argv)
    WINDOW = mainWindow()
    WINDOW.show()
    sys.exit(APP.exec_())
Okay I have played around with it enough now the SQL statement is actually entering rows of blank data in the database and not freezing up and closing so it's connecting/executing the statement. Even though I am typing something in the text boxes. So freaking close. I did take the checkbox out of the mix temporarily because it was actually causing an error. Will add it back later. For now I just added a fourth text box on the hardwareTab and using it for testing now.

from PyQt5.QtWidgets import (QLabel, QPushButton, QLineEdit, QApplication, QCheckBox, QMainWindow, QWidget,
                             QVBoxLayout, QTabWidget, QStatusBar)
import pyodbc
import sys


class mainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(385, 323)
        self.setWindowTitle("HARDWARE | SOFTWARE MANAGER")
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)

        self.tabForm = QTabWidget()
        self.tabForm.addTab(hardwareTab(), "HARDWARE")
        self.tabForm.addTab(softwareTab(), "SOFTWARE")
        self.setCentralWidget(self.tabForm)


class hardwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snLabel = QLabel("SERIAL NUMBER")
        self.snTextBox = QLineEdit()
        self.modelLabel = QLabel("MODEL")
        self.modelTextBox = QLineEdit()
        self.userLabel = QLabel("USER")
        self.userTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW HARDWARE")
        self.cfButton = QPushButton("CLEAR FIELDS")
        self.seButton = QPushButton("SEARCH/EDIT HARDWARE")
        self.activeCheckbox = QCheckBox("ACTIVE")
        self.testTextbox = QLineEdit()

        layout = QVBoxLayout(self)
        layout.addWidget(self.snLabel)
        layout.addWidget(self.snTextBox)
        layout.addWidget(self.modelLabel)
        layout.addWidget(self.modelTextBox)
        layout.addWidget(self.userLabel)
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.activeCheckbox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)
        layout.addWidget(self.testTextbox)

        self.enButton.clicked.connect(enterNewHardware)


class softwareTab(QWidget):
    def __init__(self):
        super().__init__()
        self.snLabel = QLabel("SERIAL NUMBER / KEY")
        self.snTextbox = QLineEdit()
        self.nameLabel = QLabel("APPLICATION NAME")
        self.nameTextBox = QLineEdit()
        self.userLabel = QLabel("USER")
        self.userTextBox = QLineEdit()
        self.enButton = QPushButton("ENTER NEW SOFTWARE")
        self.cfButton = QPushButton("CLEAR FIELDS")
        self.seButton = QPushButton("SEARCH/EDIT SOFTWARE")

        layout = QVBoxLayout(self)
        layout.addWidget(self.snLabel)
        layout.addWidget(self.snTextbox)
        layout.addWidget(self.nameLabel)
        layout.addWidget(self.nameTextBox)
        layout.addWidget(self.userLabel)
        layout.addWidget(self.userTextBox)
        layout.addWidget(self.enButton)
        layout.addWidget(self.cfButton)
        layout.addWidget(self.seButton)


class enterNewHardware(hardwareTab):
    def __init__(self):
        super().__init__()

        serial_number = self.snTextBox.text()
        model_name = self.modelTextBox.text()
        user_name = self.userTextBox.text()
        test_textbox = self.testTextbox.text()

        azureServer = "pythonserver5874.database.windows.net"
        azureDB = "inventoryDatabase"
        userName = "na"
        password = "na"
        driver = "{ODBC Driver 17 for SQL Server}"
        connectionString = f"DRIVER={driver};SERVER={azureServer};PORT=1433;DATABASE={azureDB};UID={userName};PWD={password}"
        conn = pyodbc.connect(connectionString)
        cursor = conn.cursor()

        sqlstatement = 'INSERT INTO inventoryDatabase.dbo.Hardware(serialNumber, modelName, userName, machineActive) VALUES (?, ?, ?, ?)'
        data = (serial_number, model_name, user_name, test_textbox)

        cursor.execute(sqlstatement, data)
        conn.commit()


if __name__ == "__main__":
    APP = QApplication(sys.argv)
    WINDOW = mainWindow()
    WINDOW.show()
    sys.exit(APP.exec_())
Pages: 1 2