Custom QDockWidget display - c++

How would you get a display of dockwidgets/centralwidget in which the dockwidget in the Qt::BottomDockWidgetArea or Qt::TopDockWidgetArea doesn't take Qt::LeftDockWidgetArea nor Qt::RighDockWidgetArea space?
This is the actual display, with 2 dockwidgets and the central widget at the top right:
This would be the preferred display:

you probably should use the QMainWindow's corner functionality to get the behavior you wanted.
Something like this may work (can't test whether its compiles, sorry):
mainWindow->setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
mainWindow->setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
mainWindow->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
mainWindow->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
See:
* QMainWindow::setCorner(...)

It seems that the (slightly bizarre) trick to get this working is to set a QMainWindow as the central widget of your main window.
Here's a PyQt port of this Qt FAQ example:
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setWindowTitle('Extended Side Dock Areas')
self.window = QtGui.QMainWindow(self)
self.window.setCentralWidget(QtGui.QTextEdit(self.window))
self.window.setWindowFlags(QtCore.Qt.Widget)
self.setCentralWidget(self.window)
self.dock1 = QtGui.QDockWidget(self.window)
self.dock1.setWidget(QtGui.QTextEdit(self.dock1))
self.window.addDockWidget(
QtCore.Qt.BottomDockWidgetArea, self.dock1)
self.dock2 = QtGui.QDockWidget(self)
self.dock2.setAllowedAreas(
QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
self.dock2.setWidget(QtGui.QLabel('Left Dock Area', self.dock2))
self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dock2)
self.dock3 = QtGui.QDockWidget(self)
self.dock3.setWidget(QtGui.QLabel('Right Dock Area', self.dock3))
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock3)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

Related

Tkinter windows decoration

I am using Tkinter for Building GUI for my python module but i don't want default windows title bar and border. I used "root.overrideredirect(True)" but with "overrideredirect()" I am losing control from my window like resizing and shifting from one place to another place. When ever I run my GUI its shows on top-left corner of my window.
from Tkinter import *
version = "v0.1"
def getinfo():
lab1 = Label(fram, text = "Your name :")
lab2 = Label(fram, text = "Your Password : ")
lab1.grid(row =1,sticky=W)
lab2.grid(row =2,sticky=W)
def Exit():
sys.exit(1)
def btn2():
btn_show = Button(fram,text = "Show")
btn_show.grid(row = 9, sticky = W)
btn_hide = Button(fram, text = "Hide")
btn_hide.grid(row = 9,column = 2, sticky = W)
root = Tk()
root.overrideredirect(True)
root.geometry("450x300")
fram = Frame(root)
fram.grid()
default_labels()
btn2()
root.mainloop()
Here is a basic example of how you can build your title bar and be able to move your window around. It is not perfect but should serve as a good starting point for your.
import Tkinter as tk
root = tk.Tk()
root.overrideredirect(True)
root.geometry("450x300")
root.config(background="darkblue")
root.columnconfigure(0, weight=1)
def move_event(event):
root.geometry('+{0}+{1}'.format(event.x_root, event.y_root))
title_frame = tk.Frame(root)
title_frame.grid(row=0, column=0, sticky="ew")
title_frame.columnconfigure(0, weight=1)
title_frame.bind('<B1-Motion>', move_event)
tk.Label(title_frame, text="Custom title bar").grid(row=0, column=0, sticky="w")
tk.Button(title_frame, text="-").grid(row=0, column=1, sticky="e")
tk.Button(title_frame, text="[]").grid(row=0, column=2, sticky="e")
tk.Button(title_frame, text="X", command=root.destroy).grid(row=0, column=3, sticky="e")
tk.Label(root, text="Test window!", fg="white", bg="darkblue").grid(row=1, column=0)
root.mainloop()
Results:
The resulting window can be dragged around though a little bit off as the window will want to move relative to the mouse position.
Yes, that's exactly what overrideredirect does. You will have to add your own bindings to allow for interactively moving and resizing the window.
The answer to the question Tkinter: windows without title bar but resizable shows how to add resizing.
The answer to the question Python/Tkinter: Mouse drag a window without borders, eg. overridedirect(1) shows how to handle the moving of the window.

How to enable autoscroll in Qtableview like in Qtextedit?

I'm using QtableView and QStandardItemModel to display logs on GUI to maintain proper spacing and filter logs. I created model and inserted data into it. Used QSortFilterProxyModel for filter strings.
self.tableView = QtGui.QTableView(self)
self.model = QtGui.QStandardItemModel(self)
self.proxy = QtGui.QSortFilterProxyModel(self)
self.proxy.setSourceModel(self.model)
self.tableView.setModel(self.proxy)
In a sec, nearly 100 logs are expected and should be shown on GUI. When new logs are appended, the view isn't auto scrolling and the slider stays only at the top. It doesn't give live feel for logging and user need to scroll manually to the end. So to overcome this, i used following syntax,
self.model.rowsInserted.connect(lambda: QtCore.QTimer.singleShot(5, self.tableView.scrollToBottom))
It gives live feel for logs, but the slider remains always in bottom and i'm not able to scroll up to see previous logs. Whenever i try to move the slider, it immediately comes down to bottom again. So this syntax doesn't meet my requirement. In QTextEdit, auto scrolling is proper and user friendly. I want the same scenario here on QtableView. Is there any alternative for auto scrolling which resembles like QTextEdit ?
To get the required behaviour, you can auto-scroll only when the previous scroll position is at the bottom. That way, whenever the user scrolls away from the bottom, auto-scrolling will be disabled; but when they scroll back to the bottom, auto-scrolling will be re-enabled. (NB: to quickly re-enable auto-scroll, right-click the scrollbar and select "Bottom" from the context menu).
Here is a simple demo:
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.table = QtGui.QTableView(self)
self.model = QtGui.QStandardItemModel(self)
self.table.setModel(self.model)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.table)
self._scroll = True
self.model.rowsAboutToBeInserted.connect(self.beforeInsert)
self.model.rowsInserted.connect(self.afterInsert)
def beforeInsert(self):
vbar = self.table.verticalScrollBar()
self._scroll = vbar.value() == vbar.maximum()
def afterInsert(self):
if self._scroll:
self.table.scrollToBottom()
def addRow(self):
self.model.appendRow([QtGui.QStandardItem(c) for c in 'ABC'])
if __name__ == '__main__':
app = QtGui.QApplication([''])
window = Window()
window.setGeometry(500, 50, 400, 300)
window.show()
timer = QtCore.QTimer()
timer.timeout.connect(window.addRow)
timer.start(200)
app.exec_()

wxpython scrolledwindow not displaying

Relatively new to python (2.7) and trying to figure out wxpython (so I apologise in advance for any poor use of code). I've got a GUI of which I have multiple switchable panels on a frame. I need the frame to be scrollable, so I've used ScrolledWindow but now some of the of the GUI elements which are below the initial frame size do not show upon scrolling on.
I've found that changing my monitor resolution solves the problem, but I want to be able to have this working regardless of resolution.
Below is an example of the problem I'm having (doesn't display hi4 and cuts off hi4)
import wx
from apanel import apanel
class simpleapp_wx(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self,parent,id,title,size=(1000,1100))
self.parent=parent
self.scroll = wx.ScrolledWindow(self, -1)
self.scroll.SetScrollbars(1,1,1000,1100)
button0=wx.Button(self.scroll,-1,"hi0",(100,610))
self.panel=apanel(self.scroll)
self.CreateStatusBar()
self.sizer= wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.panel, 1, wx.EXPAND)
self.SetSizer(self.sizer)
self.Show(True)
app=wx.App(False)
frame=simpleapp_wx(None,-1,'Demo')
frame.Show()
app.MainLoop()
and panel is in another class (in a seperate file I called apanel.py)
import wx
class apanel(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent=parent)
button=wx.Button(self,-1,"hi",(800,60))
button2=wx.Button(self,-1,"hi2",(200,600))
button3=wx.Button(self,-1,"hi3",(800,800))
button4=wx.Button(self,-1,"hi4",(500,900))
button5=wx.Button(self,-1,'hi5',(10,100))
I've found some errors in your code, it's simple to solve. Look the working panel bellow:
class simpleapp_wx(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self,parent,id,title,size=(1000,1100))
self.parent=parent
self.scroll = wx.ScrolledWindow(self, -1)
self.scroll.SetScrollbars(1,1,1000,1100)
self.CreateStatusBar()
sizer = wx.BoxSizer(wx.VERTICAL)
self.scroll.SetSizer(sizer) # The scrolledWindow sizer
self.panel = wx.Panel(self.scroll)
sizer.Add(self.panel, 0, wx.EXPAND)
button0=wx.Button(self.panel,-1,"hi0",(100,610))
Remarks:
If you use a scrolled window, create a sizer, and set the sizer in scrolled window.
The panel apanel need to be added on scrolled sizer created in line above.
The panel not resizing because simpleapp_wx (Frame) was set your size by the created BoxSizer, the order is inverse.
If you add some button after, put the apanel with parent, not scrolledwindow.
I suggest to you to use wxPython demo and docs: http://www.wxpython.org/download.php have a bunch of working examples.
Good luck in your wxpython studies!

QLineEdit hover-over Signal - when mouse is over the QlineEdit

I have a QLineEdit, and I need to know if there is a signal which can track mouse hover over that QLineEdit, and once mouse is over that QLineEdit it emits a signal.
I have seen the documents, and found we have the following signals:
cursorPositionChanged ( int old, int new )
editingFinished ()
returnPressed ()
selectionChanged ()
textChanged ( const QString & text )
textEdited ( const QString & text )
However, none of this is exactly for hover-over. Can you suggest if this can be done by any other way in PyQt4?
There is no built-in mouse-hover signal for a QLineEdit.
However, it is quite easy to achieve something similar by installing an event-filter. This technique will work for any type of widget, and the only other thing you might need to do is to set mouse tracking (although this seems to be switched on by default for QLineEdit).
The demo script below show how to track various mouse movement events:
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.edit = QtGui.QLineEdit(self)
self.edit.installEventFilter(self)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.edit)
def eventFilter(self, source, event):
if source is self.edit:
if event.type() == QtCore.QEvent.MouseMove:
pos = event.globalPos()
print('pos: %d, %d' % (pos.x(), pos.y()))
elif event.type() == QtCore.QEvent.Enter:
print('ENTER')
elif event.type() == QtCore.QEvent.Leave:
print('LEAVE')
return QtGui.QWidget.eventFilter(self, source, event)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 300, 100)
window.show()
sys.exit(app.exec_())
You can use enterEvent, leaveEvent, enterEvent is triggered when mouse enters the widget and leave event is triggered when the mouse leaves the widget. These events are in the QWidget class, QLineEdit inherits QWidget, so you can use these events in QLineEdit. I you don't see these events in QLineEdit's documentation, click on the link List of all members, including inherited members at the top of the page.

Python PyQt/PySide QMdiArea subwindows scroll not working in TabbedView

I have setup simple example using PyQt designer.See below.
I have mdiarea in in which i am adding a form as subwindow. I made form a bit lengthier than mainwindow to see if scroll-bar appears for child sub-window.
PROBLEM:
If i set mdiarea to setViewMode(QtGui.QMdiArea.TabbedView) scrollbars stop working and disappear. Howeevr If i dont use TabbedView, scrollbars work fine.
Can anyone tell me whats wrong ? I need TabbedView of mdiarea with working scrollbars.
I am using Python 2.7,PyQT 4.8.4/PySide 1.2.1 on win7.
Python Sample Code:
Comment the line self.mdiArea.setViewMode to see example working.
import sys
from PyQt4 import QtCore, QtGui
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName( "MainWindow" )
MainWindow.resize(500, 400)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName( "centralwidget" )
self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName( "verticalLayout" )
self.mdiArea = QtGui.QMdiArea(self.centralwidget)
self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
self.mdiArea.setActivationOrder(QtGui.QMdiArea.CreationOrder)
self.mdiArea.setViewMode(QtGui.QMdiArea.TabbedView)
self.mdiArea.setTabsClosable(True)
self.mdiArea.setTabsMovable(True)
self.mdiArea.setObjectName( "mdiArea" )
self.verticalLayout.addWidget(self.mdiArea)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 508, 21))
self.menubar.setObjectName( "menubar" )
self.menuAdd = QtGui.QMenu(self.menubar)
self.menuAdd.setObjectName( "menuAdd" )
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName( "statusbar" )
MainWindow.setStatusBar(self.statusbar)
self.menubar.addAction(self.menuAdd.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle( "MainWindow" )
self.menuAdd.setTitle( "&Add Form" )
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName( ("Form"))
Form.resize(400, 800)
self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setObjectName( ("gridLayout"))
self.plainTextEdit = QtGui.QPlainTextEdit(Form)
self.plainTextEdit.setMinimumSize(QtCore.QSize(0, 731))
self.plainTextEdit.setObjectName( ("plainTextEdit"))
self.gridLayout.addWidget(self.plainTextEdit, 0, 0, 1, 1)
self.buttonBox = QtGui.QDialogButtonBox(Form)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName( ("buttonBox"))
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle( "Lengthy subwindow" )
self.plainTextEdit.setPlainText( "Lengthy Form" )
class MyApp(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyApp, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
def Add_Subwindow(self):
widget = QtGui.QWidget()
self.subwin_abq = Ui_Form()
self.subwin_abq.setupUi(widget)
self.subwindow = QtGui.QMdiSubWindow(self.ui.mdiArea)
widget.setParent(self.subwindow)
self.subwindow.setWidget(widget)
self.subwindow.setWindowTitle("testing")
self.ui.mdiArea.addSubWindow(self.subwindow)
widget.show()
self.subwindow.show()
self.subwindow.widget().show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MyApp()
window.show()
window.Add_Subwindow()
sys.exit(app.exec_())
Just wanted to say thanks for the code in OP - was looking for a simple MDI example in PyQT, and yours helped I lot! I don't exactly have an answer, but this is what I can note so far: I have Python 2.7,PyQT 4.8.3, and just with commenting the setTabsClosable and setTabsMovable line, I could get your example to show like this:
I downloaded designer-qt4 and looked there about QMdiArea, there seems to be nothing called TabbedView. So I found this:
QtWidgets 5.0: QMdiArea Class | Documentation | Qt Project
enum ViewMode { SubWindowView, TabbedView }
This enum describes the view mode of the area; i.e. how sub-windows will be displayed.
SubWindowView 0 Display sub-windows with window frames (default).
TabbedView 1 Display sub-windows with tabs in a tab bar.
documentMode: This property holds whether the tab bar is set to document mode in tabbed view mode.
The way I read this: either you get to display subwindows in MDI fashion (so they can be larger than the window, with scrollbars) or the subwindows become tabs in tabbed view - and there the size of the subwindow doesn't matter anymore, so it expands to take up the available tabbed area. Also, in your code, self.ui.mdiArea.documentMode() returns False in both cases.
I also added this snippet at end of your MyApp.Add_Subwindow():
sp = self.subwindow.sizePolicy()
print sp.__dict__
#print dir(sp)
for attr in dir(sp):
try:
print "obj.%s = %s" % (attr, getattr(sp, attr))
except: pass
This dumps some interesting data (I'm not sure if those are object properties, though):
obj.ButtonBox = 2
obj.CheckBox = 4
obj.ComboBox = 8
obj.ControlType = <class 'PyQt4.QtGui.ControlType'>
obj.ControlTypes = <class 'PyQt4.QtGui.ControlTypes'>
obj.DefaultType = 1
obj.ExpandFlag = 2
obj.Expanding = 7
obj.Fixed = 0
obj.Frame = 16
...
... but also these don't change in running tabbed vs. MDI mode.
So, maybe this is the intended behavior? If that is so, that would mean you'd have to find something like a "lone" tab display widget; add programmatically several QMdiAreas; hide all of them but the default one at start; and then bind a click on respective tabs to show "their" QMdiArea and hide the others (but needless to say, I haven't tested it).