Increasing avaliable space in main window - python

I am trying to create an application using pyqt python.Application's Main window is filled with many dock widgets, some dock widgets are just used to list certain string data. These widgets are occupying more space.
the drawer to the left in the image is my interest. That drawer opens on mouse click.
Is there any way I could hide these widgets to the side of main window and open when mouse is hovered over it?
or if you know any pyqt UI element which could do this. please suggest.

The logic is to detect the desired event and show the widget, in the following example the click on the QGraphicsView is detected and then the QDockWidget that was initially hidden is shown.
from PyQt5 import QtCore, QtGui, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.dock_widget = QtWidgets.QDockWidget()
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock_widget)
list_widgets = QtWidgets.QListWidget()
list_widgets.addItems(["item{}".format(i) for i in range(100)])
self.dock_widget.setWidget(list_widgets)
self.scene = QtWidgets.QGraphicsScene(self)
self.view = QtWidgets.QGraphicsView(self.scene)
it = self.scene.addRect(QtCore.QRectF(0, 0, 300, 400))
it.setBrush(QtGui.QColor("white"))
self.view.viewport().installEventFilter(self)
self.setCentralWidget(self.view)
self.dock_widget.hide()
self.resize(640, 480)
for i in range(4):
self.menuBar().addAction("Action{}".format(i))
def eventFilter(self, obj, event):
if obj is self.view.viewport():
if event.type() == QtCore.QEvent.MouseButtonPress:
self.dock_widget.show()
return super().eventFilter(obj, event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

Related

Disable mouse wheel scroll on QscrollArea

I would like to simply disable mouse wheel scroll on QScrollArea, in order to scroll down only by clicking on right scrollbar, but I can't find any solution on the Internet.
app = QtGui.QApplication([])
sa = pg.QtGui.QScrollArea()
win = pg.GraphicsWindow()
sa.setWidget(win)
The problem is that I have a lot of graphs in my scroll area, and when I try to mousewheel on one of them, the page will scroll up or down together with the graph.
I can't find a method to call on "sa" to disable mouse wheel scroll.
I found some posts discussing about install event filter but I can't understand how to use them in this case. For example, I tried to use this:
sa.viewport().installEventFilter(???)
but I really didn't understand what arguments to pass and how to check the event.
Thank you in advance if you can help me with this problem.
You have the right idea. Event-filtering requires an object that inherits QObject to watch for the relevant events. Such objects have an eventFilter method which can be overriden to provide custom handing of all events for the watched object. If this method returns True for a given event, it will not be propagated any further. Usually the main-window is used to provide the event-filtering, like this:
import sys
from PyQt4 import QtCore, QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.scroll = QtGui.QScrollArea()
self.widget = QtGui.QGraphicsView()
self.widget.setFixedSize(600, 600)
self.scroll.setWidget(self.widget)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.scroll)
self.scroll.viewport().installEventFilter(self)
def eventFilter(self, source, event):
if (event.type() == QtCore.QEvent.Wheel and
source is self.scroll.viewport()):
return True
return super(Window, self).eventFilter(source, event)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 100, 400, 300)
window.show()
sys.exit(app.exec_())
I finally managed to resolve this, using this solution:
class Scroller(pg.QtGui.QScrollArea):
def __init__(self):
pg.QtGui.QScrollArea.__init__(self)
def wheelEvent(self, ev):
if ev.type() == QtCore.QEvent.Wheel:
ev.ignore()
app = QtGui.QApplication([])
sa = Scroller() # <======
win = pg.GraphicsWindow()
sa.setWidget(win)

Implement dragMoveEvent on QWidget in pyqt5?

does anyone know how I can implement the dragMove event on my QWidget? So basically what I want is to move my mouse over the Widget hold down my mouse button and drag it. While dragging, the widget should not be moved it should only capture the mouse coordinates while the mouse is pressed.
I have already googled and just find some drag and drop tutorials where they have dragged something into a widget etc. like text. This wasn't really helpful.
This has got nothing to do with dragging. What you actually need to do is enable mouse-tracking and then monitor mouse-move events.
Here's a simple demo:
from PyQt5 import QtCore, QtGui, QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.setMouseTracking(True)
def mouseMoveEvent(self, event):
if event.buttons() & QtCore.Qt.LeftButton:
print(event.globalPos().x(), event.globalPos().y())
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 150, 100, 100)
window.show()
sys.exit(app.exec_())
I think you are looking for mousePressEvent rather than dragMoveEvent. You would need to subclass QWidget and implement the mousePressEvent method providing your implementation:
from PyQt5.QtWidgets import QWidget
class MyWidget(QWidget):
def mousePressEvent(self, event):
print(event.pos())

pyqt popup window not displaying properly

I have created two different pyqt windows, and within one of them, by pressing a button, it should bring up another smaller window. While my code does pretty much exactly what I just dais it should do, there is a problem with the way the smaller popup window is displayed.
This is my code for displaying the windows and the button functionality:
from PyQt4 import QtGui
from EnterprisePassport import Ui_StudentEnterprisePassport
from Session_tracker import Ui_Session_tracker
class StudentEnterprisePassport(Ui_StudentEnterprisePassport):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.sessionTracker_btn.clicked.connect(self.handleButton)
self.window2 = None
def handleButton(self):
if self.window2 is None:
self.window2 = Session_tracker(self)
self.window2.show()
class Session_tracker(Ui_Session_tracker):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = StudentEnterprisePassport()
window.show()
sys.exit(app.exec_())
I can still use the functions within the window, but I can't move it, or close it, and there is no title bar. Have I done something wrong within my code for the popup window to appear like this?
Edit:
Original Session tracker window: Original window
Popup session tracker window: Popup window
In order to show the other widget in it's own window, it has to be a QMainWindow or a QDialog.
One option, if you don't want to convert your existing Session_tracker to a QDialog, is to just wrap it in a QDialog
def handleButton(self):
if self.window2 is None:
self.window2 = QtGui.QDialog(self)
lay = QtGui.QVBoxLayout()
self.window2.setLayout(lay)
self.session_tracker = Session_tracker(self.window2)
lay.addWidget(self.session_tracker)
self.window2.show()

QWidget::mouseMoveEvent not firing when cursor over child widget

I'm trying to capture the cursor coordinates as the mouse is moved within a QWidget by reimplementing QWidget::mouseMoveEvent(). With mouse tracking enabled, mouse move events are generated as I move the cursor around the main widget. However, when the cursor is placed over a child widget the mouse move events cease to fire.
Mouse press/release events work while the cursor is over the same child widget, and move events are firing correctly if the mouse button is held. I've tried enabling mouse tracking on the children too, but it doesn't seem to make a difference. How can I trigger mouse move events when the mouse is over a child widget?
Here's a minimum working example that demonstrates the problem:
import sys
from PyQt4 import QtCore, QtGui
class MyWindow(QtGui.QWidget) :
def __init__(self):
QtGui.QWidget.__init__(self)
tabs = QtGui.QTabWidget()
tab1 = QtGui.QWidget()
tab2 = QtGui.QWidget()
tabs.addTab(tab1, "Tab 1")
tabs.addTab(tab2, "Tab 2")
layout = QtGui.QVBoxLayout()
layout.addWidget(tabs)
self.setLayout(layout)
self.setMouseTracking(True)
def mouseMoveEvent(self, event):
print 'mouseMoveEvent: x=%d, y=%d' % (event.x(), event.y())
app = QtGui.QApplication(sys.argv)
window = MyWindow()
window.setFixedSize(640, 480)
window.show()
sys.exit(app.exec_())
When the mouse is moved outside of the QTabWidget the mouse coordinates are printed as expected. Inside of it nothing happens unless the mouse button is held.
The problem with your code is that you need to enable mouse tracking for all widgets explicitly. You can do this by iterating over all children of your main widget, and calling setMouseTracking(True) for each of them. Here I've overridden setMouseTracking() to do just that:
import sys
from PyQt4 import QtCore, QtGui
class MyWindow(QtGui.QWidget) :
def __init__(self):
QtGui.QWidget.__init__(self)
tabs = QtGui.QTabWidget()
tab1 = QtGui.QWidget()
tab2 = QtGui.QWidget()
tabs.addTab(tab1, "Tab 1")
tabs.addTab(tab2, "Tab 2")
layout = QtGui.QVBoxLayout()
layout.addWidget(tabs)
self.setLayout(layout)
self.setMouseTracking(True)
def setMouseTracking(self, flag):
def recursive_set(parent):
for child in parent.findChildren(QtCore.QObject):
try:
child.setMouseTracking(flag)
except:
pass
recursive_set(child)
QtGui.QWidget.setMouseTracking(self, flag)
recursive_set(self)
def mouseMoveEvent(self, event):
print 'mouseMoveEvent: x=%d, y=%d' % (event.x(), event.y())
app = QtGui.QApplication(sys.argv)
window = MyWindow()
window.setFixedSize(640, 480)
window.show()
sys.exit(app.exec_())
LAST UPDATED 19 / 8 / 2014 14 : 37 Fixed tab bar isn't track mouse move event. (your can see in my code)
I also suggest implemented QWidget.mouseMoveEvent (self, QMouseEvent) as your do. But not only root widget only because it track area of interesting widget, so your have to set mouse move event all widget can track your in your application. So, create delegate method to connect them all and if your have any signal form mouse move event, get current point of mouse it. like this;
import sys
from PyQt4 import QtGui
class QCustomWidget (QtGui.QWidget):
def __init__ (self, parent = None):
super(QCustomWidget, self).__init__(parent)
self.myQTabWidget = QtGui.QTabWidget(self)
self.my1QWidget = QtGui.QWidget()
self.my2QWidget = QtGui.QWidget()
self.myQTabWidget.addTab(self.my1QWidget, 'Tab 1')
self.myQTabWidget.addTab(self.my2QWidget, 'Tab 2')
myQLayout = QtGui.QVBoxLayout()
myQLayout.addWidget(self.myQTabWidget)
self.setLayout(myQLayout)
self.setMouseMoveEventDelegate(self)
self.setMouseMoveEventDelegate(self.myQTabWidget)
self.setMouseMoveEventDelegate(self.myQTabWidget.tabBar())
self.setMouseMoveEventDelegate(self.my1QWidget)
self.setMouseMoveEventDelegate(self.my2QWidget)
def setMouseMoveEventDelegate (self, setQWidget):
def subWidgetMouseMoveEvent (eventQMouseEvent):
currentQPoint = self.mapFromGlobal(QtGui.QCursor.pos())
print currentQPoint.x(), currentQPoint.y()
QtGui.QWidget.mouseMoveEvent(setQWidget, eventQMouseEvent)
setQWidget.setMouseTracking(True)
setQWidget.mouseMoveEvent = subWidgetMouseMoveEvent
appQApplication = QtGui.QApplication(sys.argv)
windowQCustomWidget = QCustomWidget()
windowQCustomWidget.setFixedSize(640, 480)
windowQCustomWidget.show()
sys.exit(appQApplication.exec_())
Regards,
I had the same issue and found the answer here:
self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
I would try making your QTabWidget a logical child of MyWindow by passing self when calling the QTabWidget constructor. Also pass a parent for the children of the tab widgets but pass the tab widget variable tabs to their respective constructors. Without the child hierarchy declared like this, the events might not be forwarded properly to the containing widget as its "children" will be seen as just separate widgets drawn on top of your class from the perspective of the qt scene graph / event queue.

Replace CentralWidget in MainWindow

I'm kinda new to PySide.I have a main window object which shows one widget at a time. I've been trying to change the central widget of the QMainWindow class in order to replace the visible Widget in the window when pressing a button. The problem is that the button pressed is in the Widget class, not in the main window class.
say...
class App(QtGui.QMainWindow):
def __init__(self):
super(App, self).__init__()
self.initUI()
def initUI(self):
self.statusBar().showMessage('Listo.') #Status Bar
self.login_screen = LoginScreen()
self.logged_in_screen = LoggedInScreen()
self.setCentralWidget(self.login_screen)
self.setGeometry(300, 300, 450, 600) #Window Size
self.setWindowTitle('PyTransactio - Client') #Window Title
self.setWindowIcon(QtGui.QIcon('icon.png')) #App Icon
self.show()
The pressed button is in the login_screen instance. The method called when the button is clicked is inside the LoginScreen class:
def login(self):
""" Send login data to the server in order to log in """
#Process
self.setParent(None)
Setting the parent widget to None removes the widget (login_screen) from the main window. What should I do in order to get another widget (e.g. logged_in_screen) as the central widget of the main window when the loginButton (inside the login_screen widget) is pressed?
Maybe the login method should be inside the main window class? If so, how can I connect the buttons pressed in login_screen with the main window's method?
You may use a QStackedWidget as central widget and add both the log-in screen and "logged-in" screen to it.
An example usage:
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtGui.QStackedWidget()
self.setCentralWidget(self.central_widget)
login_widget = LoginWidget(self)
login_widget.button.clicked.connect(self.login)
self.central_widget.addWidget(login_widget)
def login(self):
logged_in_widget = LoggedWidget(self)
self.central_widget.addWidget(logged_in_widget)
self.central_widget.setCurrentWidget(logged_in_widget)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Login')
layout.addWidget(self.button)
self.setLayout(layout)
# you might want to do self.button.click.connect(self.parent().login) here
class LoggedWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoggedWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.label = QtGui.QLabel('logged in!')
layout.addWidget(self.label)
self.setLayout(layout)
if __name__ == '__main__':
app = QtGui.QApplication([])
window = MainWindow()
window.show()
app.exec_()
If you do not want to use this widget, then I think you'll have to call QMainWindow.setCentralWidget every time you change the central widget.
As to where the login method should be, it depends. Probably you could define a simple interface for your mainwindow to add/remove/show specific central widgets, and call it from the login method of LoginScreen. In this way the LoginScreen class does not have to know about implementation details such as if the central widget is actually a QStackedWidget or this thing is done in an other way.
You can use QMainWindow.setCentralWidget to do this (repeatedly):
#! /usr/bin/env python3
from PySide import QtGui
from PySide import QtCore
import sys
app = QtGui.QApplication(sys.argv)
mw = QtGui.QMainWindow()
w2 = QtGui.QWidget()
pb = QtGui.QPushButton('push me', w2)
l1 = QtGui.QLabel('orig')
l2 = QtGui.QLabel('changed')
mw.setCentralWidget(l1)
pb.clicked.connect(lambda: mw.setCentralWidget(l2))
mw.show()
w2.show()
sys.exit(app.exec_())

Categories

Resources