Search code examples
pythonpython-2.7pyqtpyqt4

How to change focus on one line edit to another line edit


Here is my sample program, in this i have a two line edits i want to set the text by using the keyboard.I am getting the same text in two line edits can any one please help me how to focus the particular selected line edit.if i selected the cash_received line edit my text will set to that object.Thank you in advance. Given below is my code:

import sys
from PyQt4 import QtGui,QtCore
from functools import partial

class Example(QtGui.QWidget):

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

        self.initUI()

    def initUI(self):
        self.Vbox = QtGui.QGridLayout()
        hbox = QtGui.QHBoxLayout(spacing = 0)
        hbox.setContentsMargins(0, 0, 0, 0)
        cash_btn = QtGui.QPushButton("cash")
        card_btn = QtGui.QPushButton("Card")
        cash_btn.clicked.connect(self.cash_card_payment)
        wallet_btn = QtGui.QPushButton("wallet")
        hbox.addWidget(cash_btn)
        hbox.addWidget(card_btn)
        hbox.addWidget(wallet_btn)
        self.Vbox.addLayout(hbox,0,0)

        grid = QtGui.QGridLayout()
        self.Vbox.addLayout(grid,3,0)
        self.setLayout(self.Vbox)

        names = [
                '7', '8', '9', '-',
                '4', '5', '6', '+',
                '1', '2', '3', 'enter',
                '0', '',  '.']

        positions = [(i,j) for i in range(4) for j in range(4)]

        for position, name in zip(positions, names):
            x, y = position

            if name == '':
                continue
            button = QtGui.QPushButton(name)
            button.setFocusPolicy(QtCore.Qt.NoFocus)
            button.clicked.connect(partial(self.buttonClicked,name))

            button.setMinimumWidth(50)
            button.setMinimumHeight(50)

            if button.text() == 'enter':
                button.setMinimumHeight(110)
                grid.addWidget(button, x, y, 2,1)
            elif button.text() == '0':
                grid.addWidget(button, x, y, 1,2)
            else:
                grid.addWidget(button, x, y, 1,1)


    def cash_card_payment(self):
        print "cardssss"
        cash_payment_vbox = QtGui.QVBoxLayout()
        cash_payment_vbox.setAlignment(QtCore.Qt.AlignCenter)
        self.cash_received = QtGui.QLineEdit()
        self.cash_tender = QtGui.QLineEdit()
        cash_payment_vbox.addWidget(self.cash_received)
        cash_payment_vbox.addWidget(self.cash_tender)
        self.Vbox.addWidget(self.cash_received,1,0)
        self.Vbox.addWidget(self.cash_tender,2,0)

    def buttonClicked(self,name):
        print name
        self.cash_received.setText(name)
        #herei want to set the text for
        # cash_received objec only
        self.cash_tender.setText(name) # here i want to set the text for
        # cash_tender objec only how can i focus the one line edit to another
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    ex.show()
    ex.setWindowTitle('Calculator')
    ex.setGeometry(300, 150, 500,400)
    sys.exit(app.exec_())

Solution

  • Setting the text directly in the QLineEdit is unbeatable, say that after you use QTextEdit or another widget, and say you want to implement the clear key, etc, your solution will depend a lot on the widget.

    A less coupled solution is to use QCoreApplication::postEvent() to send a QKeyEvent to the widget that has the focus using QApplication::focusWidget()

    from PyQt4 import QtCore, QtGui
    
    class KeyPad(QtGui.QWidget):
        def __init__(self, parent=None):
            super(KeyPad, self).__init__(parent)
            grid_lay = QtGui.QGridLayout(self)
    
            keys =  [
                ("7", QtCore.Qt.Key_7 , 0, 0, 1, 1),
                ("8", QtCore.Qt.Key_8 , 0, 1, 1, 1),
                ("9", QtCore.Qt.Key_9 , 0, 2, 1, 1),
                ("-", QtCore.Qt.Key_Minus , 0, 3, 1, 1),
                ("4", QtCore.Qt.Key_4 , 1, 0, 1, 1),
                ("5", QtCore.Qt.Key_5 , 1, 1, 1, 1),
                ("6", QtCore.Qt.Key_6 , 1, 2, 1, 1),
                ("+", QtCore.Qt.Key_Plus , 1, 3, 1, 1),
                ("1", QtCore.Qt.Key_1 , 2, 0, 1, 1),
                ("2", QtCore.Qt.Key_2 , 2, 1, 1, 1),
                ("3", QtCore.Qt.Key_3 , 2, 2, 1, 1),
                ("0", QtCore.Qt.Key_0 , 3, 0, 1, 2),
                (".", QtCore.Qt.Key_Period , 3, 2, 1, 1),
                ("enter", QtCore.Qt.Key_Return , 2, 3, 2, 1)
            ]
    
            for text, key, r, c, sr, sc in keys:
                button = QtGui.QPushButton(text=text, focusPolicy=QtCore.Qt.NoFocus)
                button.setProperty("_key_", key)
                grid_lay.addWidget(button, r, c, sr, sc)
                button.clicked.connect(self.on_clicked)
                if text == "enter":
                    sp = button.sizePolicy()
                    sp.setVerticalPolicy(sp.horizontalPolicy())
                    button.setSizePolicy(sp)
    
        @QtCore.pyqtSlot()
        def on_clicked(self):
            button = self.sender()
            text = "" if button.text() == "enter" else button.text()
            key = button.property("_key_")
            widget = QtGui.QApplication.focusWidget()
            if hasattr(key, 'toPyObject'):
                key = key.toPyObject()
            if widget:
                event = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, key, QtCore.Qt.NoModifier, text)
                QtCore.QCoreApplication.postEvent(widget, event)
    
    class Widget(QtGui.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
    
            cash_btn = QtGui.QPushButton("cash", clicked=self.on_cash_btn_clicked)
            card_btn = QtGui.QPushButton("Card")
            wallet_btn = QtGui.QPushButton("wallet")
    
            self.cash_widget = QtGui.QWidget(visible=False)
            self.cash_received = QtGui.QLineEdit()
            self.cash_tender = QtGui.QLineEdit()
            cash_lay = QtGui.QVBoxLayout(self.cash_widget)
            cash_lay.addWidget(self.cash_received)
            cash_lay.addWidget(self.cash_tender)
    
            keypad = KeyPad()
    
            hbox = QtGui.QHBoxLayout()
            hbox.addWidget(cash_btn)
            hbox.addWidget(card_btn)
            hbox.addWidget(wallet_btn)
    
            vlay = QtGui.QVBoxLayout(self)
            vlay.addLayout(hbox)
            vlay.addWidget(self.cash_widget)
            vlay.addWidget(keypad)
    
        @QtCore.pyqtSlot()
        def on_cash_btn_clicked(self):
            self.cash_widget.setVisible(not self.cash_widget.isVisible())
            if self.cash_widget.isVisible():
                self.cash_received.setFocus()
    
    if __name__ == '__main__':
        import sys
        app = QtGui.QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

    PyQt5 version:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class KeyPad(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(KeyPad, self).__init__(parent)
            grid_lay = QtWidgets.QGridLayout(self)
    
            keys = [
                ("7", QtCore.Qt.Key_7, 0, 0, 1, 1),
                ("8", QtCore.Qt.Key_8, 0, 1, 1, 1),
                ("9", QtCore.Qt.Key_9, 0, 2, 1, 1),
                ("-", QtCore.Qt.Key_Minus, 0, 3, 1, 1),
                ("4", QtCore.Qt.Key_4, 1, 0, 1, 1),
                ("5", QtCore.Qt.Key_5, 1, 1, 1, 1),
                ("6", QtCore.Qt.Key_6, 1, 2, 1, 1),
                ("+", QtCore.Qt.Key_Plus, 1, 3, 1, 1),
                ("1", QtCore.Qt.Key_1, 2, 0, 1, 1),
                ("2", QtCore.Qt.Key_2, 2, 1, 1, 1),
                ("3", QtCore.Qt.Key_3, 2, 2, 1, 1),
                ("0", QtCore.Qt.Key_0, 3, 0, 1, 2),
                (".", QtCore.Qt.Key_Period, 3, 2, 1, 1),
                ("enter", QtCore.Qt.Key_Return, 2, 3, 2, 1),
            ]
    
            for text, key, r, c, sr, sc in keys:
                button = QtWidgets.QPushButton(text=text, focusPolicy=QtCore.Qt.NoFocus)
                button.setProperty("_key_", key)
                grid_lay.addWidget(button, r, c, sr, sc)
                button.clicked.connect(self.on_clicked)
                if text == "enter":
                    sp = button.sizePolicy()
                    sp.setVerticalPolicy(sp.horizontalPolicy())
                    button.setSizePolicy(sp)
    
        @QtCore.pyqtSlot()
        def on_clicked(self):
            button = self.sender()
            text = "" if button.text() == "enter" else button.text()
            key = button.property("_key_")
            widget = QtWidgets.QApplication.focusWidget()
            if hasattr(key, "toPyObject"):
                key = key.toPyObject()
            if widget:
                event = QtGui.QKeyEvent(
                    QtCore.QEvent.KeyPress, key, QtCore.Qt.NoModifier, text
                )
                QtCore.QCoreApplication.postEvent(widget, event)
    
    
    class Widget(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Widget, self).__init__(parent)
    
            cash_btn = QtWidgets.QPushButton("cash", clicked=self.on_cash_btn_clicked)
            card_btn = QtWidgets.QPushButton("Card")
            wallet_btn = QtWidgets.QPushButton("wallet")
    
            self.cash_widget = QtWidgets.QWidget(visible=False)
            self.cash_received = QtWidgets.QLineEdit()
            self.cash_tender = QtWidgets.QLineEdit()
            cash_lay = QtWidgets.QVBoxLayout(self.cash_widget)
            cash_lay.addWidget(self.cash_received)
            cash_lay.addWidget(self.cash_tender)
    
            keypad = KeyPad()
    
            hbox = QtWidgets.QHBoxLayout()
            hbox.addWidget(cash_btn)
            hbox.addWidget(card_btn)
            hbox.addWidget(wallet_btn)
    
            vlay = QtWidgets.QVBoxLayout(self)
            vlay.addLayout(hbox)
            vlay.addWidget(self.cash_widget)
            vlay.addWidget(keypad)
    
        @QtCore.pyqtSlot()
        def on_cash_btn_clicked(self):
            self.cash_widget.setVisible(not self.cash_widget.isVisible())
            if self.cash_widget.isVisible():
                self.cash_received.setFocus()
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())