Qt (via Common Lisp qtools): QLineEdit is not activated when pressed, but gets focus on TAB

Problem

I had a rather strange problem: QLineEditobjects in the interface cannot be accessed by clicking on them, but using them Tab, they get focus and respond to keyboard input. But even when they have a focus, they do not respond to clicks. What makes things weirder is that the last added one QLineEditresponds to clicks.

Additional problem: editors inaccessible to the mouse do not display prompts.

I use Common Lisp qtools to create an interface, so I will need to explain how this works. In short, I add linear changes one by one in the loop, they are all created in the same way and added to QGridLayout.

Updated . The following is a possible source of the problem.

Options Widget

The parameter widget is used to represent a single input parameter. Each parameter has a name, value and units. The name and units are displayed as labels, the value is editable and is presentedQLineEdit

(define-widget parameter-widget (QWidget)
  ((parameter :initarg :parameter)))

(define-subwidget (parameter-widget label) (q+:make-qlabel parameter-widget)
  (setf (q+:text label) (parameter-base-name parameter)))

(define-subwidget (parameter-widget entry) (q+:make-qlineedit parameter-widget)
  (setf (q+:alignment entry) +align-right+)
  (setf (q+:text entry) (format nil "~A" (parameter-value parameter)))
  (setf (q+:tool-tip entry) (parameter-base-description parameter)))

(define-subwidget (parameter-widget units) (q+:make-qlabel parameter-widget)
  (setf (q+:text units) (parameter-units parameter)))

To indicate that the parameter value has been changed, it parameter-widgetwill generate a new signal parameter-changed(it translates into the "parameter Changed " signal for Qt):

(define-signal (parameter-widget parameter-changed) ())

, parameter-changed:

(define-slot (parameter-widget parameter-changed) ((new-text string))
  (declare (connected entry (text-changed string)))
  (handler-case
      (let ((new-number (parse-number new-text)))
        (setf (parameter-value parameter) new-number)
        (signal! parameter-widget (parameter-changed)))
    (error nil)))

parameter (factory):

(defmethod make-parameter-ui ((object parameter))
  (make-instance 'parameter-widget :parameter object))

parameter-container (. ):

(defmethod add-to-grid ((widget parameter-widget) grid row column)
  (with-slots (label entry units) widget
    (q+:add-widget grid label row column 1 1)
    (q+:add-widget grid entry row (1+ column) 1 1)
    (q+:add-widget grid units row (+ column 2) 1 1)))

, parameter-widget - . parameter-container:

(define-widget parameter-container-widget (QWidget)
  ((parameter-container :initarg :parameter-container)))

parameter-changed parameter

(define-slot (parameter-container-widget parameter-changed) ()
  (format t "~&Re-emitting the signal...~%")
  (signal! parameter-container-widget (parameter-changed)))

layout - QGridLayout, parameter-widget parameter -children parameter-container. , :

  • ,
  • parameter-widget
  • layout
  • parameter-changed .

:

(define-subwidget (parameter-container-widget layout)
    (q+:make-qgridlayout parameter-container-widget)
  (loop for p in (parameter-container-children parameter-container)
     for row from 0
     do (let ((parameter-widget (make-parameter-ui p)))
          (setf (q+:parent parameter-widget) parameter-container-widget)
          (add-to-grid parameter-widget layout row 0)
          (connect! parameter-widget (parameter-changed)
                    parameter-container-widget
                    (parameter-changed)))))

parameter-widget parameter-container:

(defmethod add-to-grid ((widget parameter-container-widget) grid row column)
  (q+:add-widget grid widget row column 1 1))

(factory):

(defmethod make-parameter-ui ((object parameter-container))
  (make-instance 'parameter-container-widget :parameter-container object))

Qt4.8, Common Lisp: SBCL 1.3.7, qtools Quicklisp, : Ubuntu 16.04

Update

Windows 10

2:

, : . :

(ql:quickload '(:qtools :qtcore :qtgui))

(defpackage :qtexample
  (:use #:cl+qt))

(in-package qtexample)

(in-readtable :qtools)


(defclass parameter ()
  ((name :initarg :name :accessor parameter-name)
   (value :initarg :value :accessor parameter-value)
   (units :initarg :units :accessor parameter-units)))

(defun parameter (name value units)
  (make-instance 'parameter
    :name name
    :value value
    :units units))

(defvar *mass* (parameter "mass" 1d0 "kg"))
(defvar *velocity* (parameter "velocity" 0.5d0 "m/s"))

(defvar *temperature* (parameter "temperature" 300d0 "K"))
(defvar *pressure* (parameter "pressure" 1d5 "Pa"))

(define-widget parameter-widget (QWidget)
  ((parameter
    :initarg :parameter
    :accessor parameter-widget-parameter)))

(define-subwidget (parameter-widget label)
    (q+:make-qlabel parameter-widget)
  (setf (q+:text label) (parameter-name parameter)))

(defmethod make-ui ((object parameter))
  (make-instance 'parameter-widget :parameter object))

(defconstant +align-right+ 2)

(define-subwidget (parameter-widget entry)
    (q+:make-qlineedit parameter-widget)
  (setf (q+:alignment entry) +align-right+)
  (setf (q+:text entry) (format nil "~A" (parameter-value parameter))))

(define-subwidget (parameter-widget units)
    (q+:make-qlabel parameter-widget)
  (setf (q+:text units) (parameter-units parameter)))

(define-signal (parameter-widget parameter-changed) ())

(define-slot (parameter-widget entry) ((new-text string))
  (declare (connected entry (text-changed string)))
  (format t "~&Parameter has changed~%")
  (handler-case
      (let ((new-number (parse-number:parse-number new-text)))
        (setf (parameter-value parameter) new-number)
        (signal! parameter-widget (parameter-changed)))
    (error nil)))

(defmethod add-to-grid ((widget parameter-widget) grid row column)
  (with-slots (label entry units) widget
    (q+:add-widget grid label row column 1 1)
    (q+:add-widget grid entry row (1+ column) 1 1)
    (q+:add-widget grid units row (+ column 2) 1 1)
    (list (1+ row) (+ column 3))))

(define-widget parameter-widget-window (QWidget)
  ((parameter :initarg :parameter)))


(define-subwidget (parameter-widget-window parameter-widget)
    (make-ui parameter))

(define-subwidget (parameter-widget-window grid)
    (q+:make-qgridlayout  parameter-widget-window)
  (add-to-grid parameter-widget grid 0 0))

(defun parameter-example (parameter)
  (with-main-window
      (window (make-instance 'parameter-widget-window
                :parameter parameter))))

(define-widget parameter-container-widget (QWidget)
  ((parameter-container
    :initarg :parameter-container
    :accessor parameter-container-widget-parameter-container)))

(defmethod make-ui ((object list))
  (make-instance 'parameter-container-widget :parameter-container object))

(define-slot (parameter-container-widget parameter-changed) ()
  (format t "~&Re-emitting the signal...~%")
  (signal! parameter-container-widget (parameter-changed)))

(define-subwidget (parameter-container-widget layout)
    (q+:make-qgridlayout parameter-container-widget)
  (let* ((parameter-widgets (loop for p in parameter-container
                               collect (make-ui p))))
    (loop for p in parameter-widgets
       for row from 0
       do (progn
            (setf (q+:parent p) parameter-container-widget)
            (add-to-grid p layout row 0)
            (connect! p
                      (parameter-changed)
                      parameter-container-widget
                      (parameter-changed))))))

(define-widget parameter-container-widget-window (QWidget)
  ((parameter-container :initarg :parameter-container)))

(define-subwidget (parameter-container-widget-window container-widget)
    (make-ui parameter-container)
  (setf (q+:parent container-widget) parameter-container-widget-window))

(define-slot (parameter-container-widget-window parameter-changed) ()
  (declare (connected container-widget (parameter-changed)))
  (format t "~&Got parameter changed~%"))


(defmethod add-to-grid ((widget parameter-container-widget) grid row column)
  (q+:add-widget grid widget row column))

(defun example-parameter-container (parameter-container)
  (with-main-window
      (window (make-instance 'parameter-container-widget-window
                :parameter-container parameter-container))))

;; to run:
(example-parameter-container (list *mass* *velocity*))

.

(setf (q+:parent p) parameter-container-widget) 

- p ( -) parameter-container-widget. , .

p - ( entry, QLineEdit), , p ! parameter-widget : . .

+4
1

@KubaOber @Shinmera . .

(, :PARSE-NUMBER):

(ql:quickload '(:qtools :qtcore :qtgui :parse-number))

(defpackage :qtexample
  (:use #:cl+qt))

(in-package qtexample)

(in-readtable :qtools)


(defclass parameter ()
  ((name :initarg :name :accessor parameter-name)
   (value :initarg :value :accessor parameter-value)
   (units :initarg :units :accessor parameter-units)))

(defun parameter (name value units)
  (make-instance 'parameter
    :name name
    :value value
    :units units))

(defvar *mass* (parameter "mass" 1d0 "kg"))
(defvar *velocity* (parameter "velocity" 0.5d0 "m/s"))

(defvar *temperature* (parameter "temperature" 300d0 "K"))
(defvar *pressure* (parameter "pressure" 1d5 "Pa"))

PARAMETER-WIDGET , ( -, - . ADD-TO-GRID). , QObject, QWidget. - (DEFINE-SUBWIDGET ...). , -: , -.

(define-widget parameter-widget (QObject)
  ((parameter
    :initarg :parameter
    :accessor parameter-widget-parameter)
   (label :initform (q+:make-qlabel))
   (entry :initform (q+:make-qlineedit))
   (units :initform (q+:make-qlabel))))

INITIALIZE-INSTANCE :AFTER:

(defconstant +align-right+ 2)

(defmethod initialize-instance :after ((object parameter-widget) &key)
  (with-slots (parameter label entry units) object
    (setf (q+:text label) (parameter-name parameter))
    (setf (q+:text entry) (format nil "~A" (parameter-value parameter)))
    (setf (q+:alignment entry) +align-right+)
    (setf (q+:text units) (parameter-units parameter))))

( , , ):

(defmethod make-ui ((object parameter))
  (make-instance 'parameter-widget :parameter object))

(define-signal (parameter-widget parameter-changed) ())

(define-slot (parameter-widget entry) ((new-text string))
  (declare (connected entry (text-changed string)))
  (format t "~&Parameter has changed~%")
  (handler-case
      (let ((new-number (parse-number:parse-number new-text)))
        (setf (parameter-value parameter) new-number)
        (signal! parameter-widget (parameter-changed)))
    (error nil)))

(defmethod add-to-grid ((widget parameter-widget) grid row column)
  (with-slots (label entry units) widget
    (q+:add-widget grid label row column 1 1)
    (q+:add-widget grid entry row (1+ column) 1 1)
    (q+:add-widget grid units row (+ column 2) 1 1)
    (list (1+ row) (+ column 3))))

, . PARAMETER-WIDGET , .

(define-widget parameter-widget-window (QWidget)
  ((parameter :initarg :parameter)
   (parameter-widget)))

:

(define-subwidget (parameter-widget-window grid)
    (q+:make-qgridlayout  parameter-widget-window))

PARAMETER-WIDGET . : PARAMETER-WIDGET . INITIALIZE-INSTANCE :AFTER :

(defmethod initialize-instance :after ((object parameter-widget-window) &key)
  (with-slots (parameter parameter-widget grid) object
    (setf parameter-widget (make-ui parameter))
    (setf (q+:parent parameter-widget) object)
    (add-to-grid parameter-widget grid 0 0)))

:

(defun parameter-example (parameter)
  (with-main-window
      (window (make-instance 'parameter-widget-window
                :parameter parameter))))

: (parameter-example *mass*)

PARAMETER-CONTAINER-WIDGET - . :

(define-widget parameter-container-widget (QWidget)
  ((parameter-container
    :initarg :parameter-container
    :accessor parameter-container-widget-parameter-container)))

(defmethod make-ui ((object list))
  (make-instance 'parameter-container-widget :parameter-container object))

(define-slot (parameter-container-widget parameter-changed) ()
  (format t "~&Re-emitting the signal...~%")
  (signal! parameter-container-widget (parameter-changed)))

LAYOUT . p (PARAMETER-WIDGET) PARAMETER-WIDGET-CONTAINER, .

(define-subwidget (parameter-container-widget layout)
    (q+:make-qgridlayout parameter-container-widget)
  (let* ((parameter-widgets (loop for p in parameter-container
                               collect (make-ui p))))
    (loop for p in parameter-widgets
       for row from 0
       do (progn
            (add-to-grid p layout row 0)
            (let ((pp p))
              (setf (q+:parent pp) parameter-container-widget))
            (connect! p
                      (parameter-changed)
                      parameter-container-widget
                      (parameter-changed))))))

( , , . ):

(defmethod add-to-grid ((widget parameter-container-widget) grid row column)
  (q+:add-widget grid widget row column))

:

(define-widget parameter-container-widget-window (QWidget)
  ((parameter-container :initarg :parameter-container)))

(define-subwidget (parameter-container-widget-window container-widget)
    (make-ui parameter-container)
  (setf (q+:parent container-widget) parameter-container-widget-window))

(define-slot (parameter-container-widget-window parameter-changed) ()
  (declare (connected container-widget (parameter-changed)))
  (format t "~&Got parameter changed~%"))

(defun example-parameter-container (parameter-container)
  (with-main-window
      (window (make-instance 'parameter-container-widget-window
                :parameter-container parameter-container))))

: (example-parameter-container (list *mass* *velociy*))

(example-parameter-container (list *mass* *velocity* (list *temperature* *pressure*))) 

, ADD-TO-GRID PARAMETER-CONTAINER-WIDGET , .

+5

Source: https://habr.com/ru/post/1651216/


All Articles