[PyQt] QPlainTextEdit not created in a widget through a QAction

Mark Summerfield list at qtrac.plus.com
Sun Jun 6 07:58:42 BST 2010

Hi Gerardo,

I'm not sure I can help but have a few comments...

On 2010-06-06, Gerardo Gutierrez wrote:
> Hi, I'm writing a frontend for ipython and I've a problem with a context
> menu...
> The frontend is based on mathematica so it has cells when you can write
>  code and execute it (not yet implemented)
> So the cells are QPlainTextEdits which are embedded in a QWidget:
> class Notebook(QtCore.QObject):
>       def __init__(self,parent):
>         QtCore.QObject.__init__(self)
>         self._container=QtGui.QWidget(parent)
>         self._nb_menu=NbContextMenu(self._container)

I don't really understand why Notebook doesn't inherit QWidget directly.

> ew_cell_slot) self._container.mousePressEvent = self.nb_mouse_click_event
> so the last line is for the context menu to popup con right click:
>         def nb_mouse_click_event(self,event):
>             if event.button()==QtCore.Qt.RightButton:
>                 self._nb_menu.popup(event.globalPos())

Do you really need to implement such a low-level event handler?
If Notebook inherits QWidget rather than QObject you can set its context
menu policy either to Qt.ActionsContextMenu (in which case you can add
the actions directly to the Notebook using addAction()), or to
Qt.CustomContextMenu (in which case you connect the
customContextmenuRequested() signal to a slot where you create the
context menu yourself).
> The NbContextMenu class is described here:
> class NbContextMenu(QtGui.QMenu):
>     def __init__(self,parent):
>         QtGui.QMenu.__init__(self,parent)
>         self.set_actions()
>         def set_actions(self):
>             self.new_cell=QtGui.QAction("new cell",self)
>             self.addAction(self.new_cell)

I don't understand why you need this class. If Notebook is a QWidget you
can use one of the techniques I mentioned above. But if it is a QObject
then why not use a plain QMenu and use its addAction() method to add
actions to it directly?

> The connection showed above calls a slot which calls a function to create 
> new cell in the QWidget called _container:
> def new_input_cell(self,index=0):
>     cell=InputCell(self._container)
>     if index==0:
>         prev_cell=self._cell_list[len(self._cell_list)-1]
> 5,60)) self._cell_list.append(cell)
>     else:
>         prev_cell=self._cell_list[index-1]
> 5,60)) self._cell_list.insert(index,cell)
>    cell.index=self._cell_list.index(cell)
>    self.connect(cell,QtCore.SIGNAL("cell_index"),self.active_cell_signal)
> )

Using hard-coded numbers will make the application fragile. You might
get away with little tweaks like +5, but for the 39 and 60 it would be
better to compute them, for example based on QApplication.globalStrut().

> The problem is then, that through the QMenu QAction the cells are being
> appended but not showed. This doesn't happen if I call the function
> new_input_cell from the constructor in the mainwindow class.

I don't know why, but I am suspicious that you have made the QAction's
parent be the QMenu; I would try making the QAction's parent the QWidget
the QMenu is associated with (e.g., the Notebook if you change it to be
a QWidget or self._container otherwise).

Good luck!

Mark Summerfield, Qtrac Ltd, www.qtrac.eu
    C++, Python, Qt, PyQt - training and consultancy
        "Advanced Qt Programming" - ISBN 0321635906

More information about the PyQt mailing list