2017-05-19 6 views
1

Kann mir jemand helfen, die Punkte zu verbinden. Ich lerne immer noch, wie man programmiert, und ich versuche OOP zu lernen, indem ich eine einfache GUI in PYQT mache.Anfänger: Pyqt 4 verbindet Touch-Tastatur mit einem Browser-Widget

Ich versuche es, aber ich weiß nicht, wie man zwei Widgets verbindet. Eines ist ein Webbrowser-Beispiel und das zweite ist ein Beispiel für eine Berührungstastatur. Die Touch-Tastatur muss aufgerufen werden, wenn Sie die Zeile im Browser-Widget berühren, um eine URL hinzuzufügen.

-Code für MyBrowser widget:

import sys 
from PyQt4.QtGui import QApplication 
from PyQt4.QtCore import QUrl 
from PyQt4.QtWebKit import QWebView 
from PyQt4.QtGui import QGridLayout, QLineEdit, QWidget 

class UrlInput(QLineEdit): 
    def __init__(self, browser): 
     super(UrlInput, self).__init__() 
     self.browser = browser 
     # add event listener on "enter" pressed 
     self.returnPressed.connect(self._return_pressed) 

    def _return_pressed(self): 
     url = QUrl(self.text()) 
     # load url into browser frame 
     browser.load(url) 

if __name__ == "__main__": 
    app = QApplication(sys.argv) 

    # create grid layout 
    grid = QGridLayout() 
    browser = QWebView() 
    browser.load(QUrl('http://google.com')) 
    url_input = UrlInput(browser) 
    # url_input at row 1 column 0 of our grid 
    grid.addWidget(url_input, 1, 0) 
    # browser frame at row 2 column 0 of our grid 
    grid.addWidget(browser, 2, 0) 

    # main app window 
    main_frame = QWidget() 
    main_frame.setLayout(grid) 
    main_frame.show() 

    # close app when user closes window 
    sys.exit(app.exec_()) 

-Code für KeyboardTouch:

from PyQt4 import QtGui, QtCore 
from decimal import Decimal 



# applicationle widgets 
SIP_WIDGETS = [QtGui.QLineEdit] 


class MyFlatPushButton(QtGui.QPushButton): 
    def __init__(self, caption, min_size=(50, 20)): 
     self.MIN_SIZE = min_size 
     QtGui.QPushButton.__init__(self, caption) 
     self.setFocusPolicy(QtCore.Qt.NoFocus) 

    def sizeHint(self): 
     return QtCore.QSize(self.MIN_SIZE[0], self.MIN_SIZE[1]) 


class SoftInputWidget(QtGui.QDialog): 
    def __init__(self, parent_object, keyboard_type='default'): 
     QtGui.QDialog.__init__(self) 
     self.setWindowFlags(QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint) 
     self.INPUT_WIDGET = None 
     self.PARENT_OBJECT = parent_object 
     self.signalMapper = QtCore.QSignalMapper(self) 

     self.NO_ORD_KEY_LIST = list() 
     self.NO_ORD_KEY_LIST.append(QtCore.Qt.Key_Left) 
     self.NO_ORD_KEY_LIST.append(QtCore.Qt.Key_Up) 
     self.NO_ORD_KEY_LIST.append(QtCore.Qt.Key_Right) 
     self.NO_ORD_KEY_LIST.append(QtCore.Qt.Key_Down) 
     self.NO_ORD_KEY_LIST.append(QtCore.Qt.Key_Backspace) 
     self.NO_ORD_KEY_LIST.append(QtCore.Qt.Key_Enter) 
     self.NO_ORD_KEY_LIST.append(QtCore.Qt.Key_Tab) 
     self.NO_ORD_KEY_LIST.append(QtCore.Qt.Key_Escape) 

     self.do_layout(keyboard_type) 

     self.signalMapper.mapped[int].connect(self.buttonClicked) 

    def do_layout(self, keyboard_type='default'): 
     """ 
     @param keyboard_type: 
     @return: 
     """ 
     gl = QtGui.QVBoxLayout() 
     self.setFont(self.PARENT_OBJECT.font()) 
     number_widget_list = [] 
     sym_list = range(0, 10) 
     for sym in sym_list: 
      button = MyFlatPushButton(str(sym)) 
      button.KEY_CHAR = ord(str(sym)) 
      number_widget_list.append(button) 

     button = MyFlatPushButton('*') 
     button.KEY_CHAR = ord('*') 
     number_widget_list.append(button) 

     # alphabets 
     alpha_widget_list = [] 
     sym_list = ['q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p','@', 
        'new_row', 
        'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '-', '/', 
        'new_row', 
        'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', ':'] 

     for sym in sym_list: 
      if sym == 'new_row': 
       alpha_widget_list.append('new_row') 
      else: 
       button = MyFlatPushButton(sym) 
       button.KEY_CHAR = ord(sym) 
       alpha_widget_list.append(button) 



     # back space 
     control_widget_list = [] 

     # close 
     button = MyFlatPushButton('Esc') 
     button.KEY_CHAR = QtCore.Qt.Key_Escape 
     control_widget_list.append(button) 
     control_widget_list.append('sep') 

     button = MyFlatPushButton('Del') 
     button.setToolTip('Backspace') 
     button.KEY_CHAR = QtCore.Qt.Key_Backspace 
     control_widget_list.append(button) 
     control_widget_list.append('sep') 

     # tab 
     button = MyFlatPushButton('TAB') 
     button.KEY_CHAR = QtCore.Qt.Key_Tab 
     control_widget_list.append(button) 
     control_widget_list.append('sep') 

     # space 
     button = MyFlatPushButton('Space', min_size=(70, 30)) 
     button.KEY_CHAR = QtCore.Qt.Key_Space 
     control_widget_list.append(button) 
     control_widget_list.append('sep') 



     # enter 
     button = MyFlatPushButton('ENTER', min_size=(60, 30)) 
     button.KEY_CHAR = QtCore.Qt.Key_Enter 
     control_widget_list.append(button) 
     control_widget_list.append('sep') 

     alist = list() 
     alist.append((QtCore.Qt.Key_Left, 'Left')) 
     alist.append((QtCore.Qt.Key_Right, 'Right')) 
     alist.append((QtCore.Qt.Key_Up, 'Up')) 
     alist.append((QtCore.Qt.Key_Down, 'Down')) 

     for key in alist: 
      button = MyFlatPushButton(key[1]) 
      button.KEY_CHAR = key[0] 
      control_widget_list.append(button) 

     MAX_COL = 10 
     col = 0 
     tlist = list() 

     if keyboard_type == 'numeric': 
      widget_list = number_widget_list 
     elif keyboard_type == 'alpha': 
      widget_list = alpha_widget_list 
     else: 
      widget_list = list() 
      widget_list.extend(number_widget_list) 
      widget_list.append('new_row') 
      widget_list.extend(alpha_widget_list) 

     widget_list.append('new_row') 
     widget_list.extend(control_widget_list) 

     for widget in widget_list: 
      if widget == 'new_row': 
       col = MAX_COL 
      elif widget == 'sep': 
       tlist.append(self.get_vline()) 
       continue 
      else: 
       tlist.append(widget) 
       widget.clicked.connect(self.signalMapper.map) 
       self.signalMapper.setMapping(widget, widget.KEY_CHAR) 

      if col == MAX_COL: 
       col = 0 
       v = QtGui.QHBoxLayout() 
       v.addStretch() 
       v.setSpacing(2) 
       map(v.addWidget, tlist) 
       v.addStretch() 
       gl.addLayout(v) 
       tlist = [] 
      else: 
       col += 1 

     v = QtGui.QHBoxLayout() 
     v.setSpacing(5) 
     v.addStretch() 

     map(v.addWidget, tlist) 
     v.addStretch() 
     gl.addLayout(v) 
     gl.setContentsMargins(0, 0, 0, 0) 
     gl.setSpacing(3) 
     gl.setSizeConstraint(gl.SetFixedSize) 

     self.setLayout(gl) 


    #moguce za iskoristi za back botun 
    def reject(self): 
     self.buttonClicked(QtCore.Qt.Key_Escape) 

    def buttonClicked(self, char_ord): 
     w = self.INPUT_WIDGET 
     if char_ord in self.NO_ORD_KEY_LIST: 
      keyPress = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, char_ord, QtCore.Qt.NoModifier, '') 
     else: 
      keyPress = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, char_ord, QtCore.Qt.NoModifier, chr(char_ord)) 

     # send keypress event to widget 
     QtGui.QApplication.sendEvent(w, keyPress) 

     # line edit returnPressed event is triggering twice for press and release both 
     # that is why do not send release event for special key 
     if char_ord not in self.NO_ORD_KEY_LIST: 
      keyRelease = QtGui.QKeyEvent(QtCore.QEvent.KeyPress, char_ord, QtCore.Qt.NoModifier, '') 
      QtGui.QApplication.sendEvent(w, keyRelease) 

     # hide on enter or esc button click 
     if char_ord in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Escape): 
      self.hide() 

    def show_input_panel(self, widget): 
     self.INPUT_WIDGET = widget 
     self.show() 
     self.update_panel_position() 

    def update_panel_position(self): 
     widget = self.INPUT_WIDGET 
     if not widget: return 

     widget_rect = widget.rect() 
     widget_bottom = widget.mapToGlobal(QtCore.QPoint(widget.frameGeometry().x(), widget.frameGeometry().y())).y() 
     screen_height = QtGui.qApp.desktop().availableGeometry().height() 
     input_panel_height = self.geometry().height() + 5 

     if (screen_height - widget_bottom) > input_panel_height: 
      # display input panel at bottom of widget 
      panelPos = QtCore.QPoint(widget_rect.left(), widget_rect.bottom() + 2) 
     else: 
      # display input panel at top of widget 
      panelPos = QtCore.QPoint(widget_rect.left(), widget_rect.top() - input_panel_height) 

     panelPos = widget.mapToGlobal(panelPos) 
     self.move(panelPos) 

    def _get_line(self, vertical=True): 
     line = QtGui.QFrame() 
     line.setContentsMargins(0, 0, 0, 0) 
     if vertical is True: 
      line.setFrameShape(line.VLine) 
     else: 
      line.setFrameShape(line.HLine) 
     line.setFrameShadow(line.Sunken) 
     return line 

    def get_hline(self): 
     return self._get_line(vertical=False) 

    def get_vline(self): 
     return self._get_line() 


class TouchInterface(QtCore.QObject): 
    def __init__(self, PARENT_WIDGET): 
     QtCore.QObject.__init__(self) 
     self._PARENT_WIDGET = PARENT_WIDGET 
     self._input_panel_all = SoftInputWidget(PARENT_WIDGET, 'default') 
     # self._input_panel_numeric = SoftInputWidget(PARENT_WIDGET, 'numeric') 

    def childEvent(self, event): 
     if event.type() == QtCore.QEvent.ChildAdded: 
      if isinstance(event.child(), *SIP_WIDGETS): 
       event.child().installEventFilter(self) 

    def eventFilter(self, widget, event): 
     if self._PARENT_WIDGET.focusWidget() == widget and event.type() == QtCore.QEvent.MouseButtonPress: 
      if hasattr(widget, 'keyboard_type'): 
       if widget.keyboard_type == 'default': 
        self._input_panel_all.show_input_panel(widget) 
       # elif widget.keyboard_type == 'numeric': 
        # self._input_panel_numeric.show_input_panel(widget) 

     return False 


class TouchInputWidget(QtGui.QWidget): 
    def __init__(self): 
     QtGui.QWidget.__init__(self) 
     self.touch_interface = TouchInterface(self) 

    def childEvent(self, event): 
     self.touch_interface.childEvent(event) 

    def eventFilter(self, widget, event): 
     return self.touch_interface.eventFilter(widget, event) 


class ExampleWidget(TouchInputWidget): 
    def __init__(self): 
     TouchInputWidget.__init__(self) 

     #self.txtNumeric = QtGui.QLineEdit() 
     # actiate touch input 
     # self.txtNumeric.keyboard_type = 'numeric' 

     self.txtText = QtGui.QLineEdit() 
     # activate touch input 
     self.txtText.keyboard_type = 'default' 

     gl = QtGui.QVBoxLayout() 
     # gl.addWidget(self.txtNumeric) 
     gl.addWidget(self.txtText) 

     self.setWindowTitle('Touch Input Demo') 
     self.setLayout(gl) 

if __name__ == '__main__': 
    app = QtGui.QApplication([]) 
    ExampleWidget().show() 
    app.exec_() 

Antwort

0

Ich bin nicht so sicher, ob ich verstanden, was Sie brauchen, von wo aus ich Sie nur sehen, einige zeigen wollen Tastatur, wenn Sie in ein QLineEdit klicken. Wenn es das ist, was Sie brauchen, würde ich Ihnen sagen, dass Sie ein Signal verwenden und einige Standardmethoden außer Kraft setzen und das gewünschte Verhalten darin implementieren sollen.

Werfen Sie einen Blick auf dieses kleine Beispiel sehen, ob es Sinn macht, und wenn Sie diese Argumentation in Ihre App „)

import sys 

from PyQt5.QtCore import pyqtSignal 
from PyQt5.QtWidgets import QApplication 
from PyQt5.QtWidgets import QHBoxLayout 
from PyQt5.QtWidgets import QLineEdit 
from PyQt5.QtWidgets import QMainWindow 
from PyQt5.QtWidgets import QPushButton 
from PyQt5.QtWidgets import QWidget 

class MainWindow(QMainWindow): 

    def __init__(self): 
     super(MainWindow, self).__init__() 
     self.central_widget = QWidget() 
     self.cw_layout = QHBoxLayout() 
     self.central_widget.setLayout(self.cw_layout) 
     self.setCentralWidget(self.central_widget) 

     self.line = LineEdit() 
     self.kb = KeyBoard() 

     self.cw_layout.addWidget(self.line) 

     self.create_connections() 

    def create_connections(self): 
     self.line.signal_evoke_kb.connect(self.show_kb) 

    def show_kb(self): 
     if self.kb.isHidden(): 
      self.kb.show() 
     else: 
      self.kb.hide() 


class LineEdit(QLineEdit): 

    signal_evoke_kb = pyqtSignal() 

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

    def mousePressEvent(self, QMouseEvent): 
     super(LineEdit, self).mousePressEvent(QMouseEvent) 
     self.signal_evoke_kb.emit() 

class KeyBoard(QWidget): 

    def __init__(self): 
     super(KeyBoard, self).__init__() 
     self.layout = QHBoxLayout() 
     for key in ['q','w','e','r','t','y']: 
      self.layout.addWidget(QPushButton(key)) 
     self.setLayout(self.layout) 


if __name__ == "__main__": 
    app = QApplication(sys.argv) 
    mw = MainWindow() 
    mw.show() 
    sys.exit(app.exec_()) 

Ich verwende PyQt5 Sie müssten so wahrscheinlich verwenden konnte einfach ändern die Importe

+0

Danke für die Hilfe, ich werde versuchen, Ihr Beispiel in meiner App zu implementieren! Ich musste verstehen, wie man ein Widget "Touch-Tastatur" jedes Mal, wenn ich auf Zeile zum Bearbeiten "QLineEdit" klicken Dieses Beispiel des Webbrowsers verwirrte mich wegen dieser Klasse UrlInput (QLineEdit) .Diese Klasse ruft ein QLineEdit auf und wegen meines Fehlens Erfahrung, ich weiß nicht, wie "Touch-Tastatur" dort implementieren. – Astabil

+0

Ja, ich verstehe vollkommen, bedenken Sie, dass jedes Mal, wenn Sie eine Variation von etwas brauchen, Sie eine Klasse erstellen müssen, diese Klasse erweitern und einige Methoden aus ihrer Vererbung überschreiben. Eine weitere gute Sache, die Sie sehen sollten, ist Filter und Filter Installation, das sind die besten Möglichkeiten, Ereignisse, die Sie in Qt fangen wollen, zu bekommen. Schau einfach in die API, da gibt es echt tolle Beispiele, und ohne Zweifel auch StackOverflow ") – yurisnm

Verwandte Themen