I would like to know how to disable the window Maximise button in pyqt4. I am at present using QWidget.setFixedSize (self, QSize) to prevent user window resizing, however the maximise button is still enabled and when pressed causes the application to move to the top left corner of the screen. I am basically wanting to replicate the behaviour of the Windows calculator application, where the maximise icon is greyed out. Does anyone know how to achieve this with PyQt4?
Haven't worked with it but research seems to point to messing with the window flags.
QWidget has a method called setWindowFlags.
Here is the doc for the Qt.WindowFlags class.
Here is a reference for all of the flags. Look for Qt.WindowMaximizeButtonHint
In general it seems like you need to find a way to enable the Qt.CustomizeWindowHint flag and disable the Qt.WindowMaximizeButtonHint flag. Either way, you probably want this in addition to setFixedSize so that's a good start.
Edit:
Something like
win.setWindowFlags(win.windowFlags() | QtCore.Qt.CustomizeWindowHint)
win.setWindowFlags(win.windowFlags() & ~QtCore.Qt.WindowMaximizeButtonHint)
Assuming your import is something like this
from PyQt4 import QtCore
This would turn on the CustomizeWindowHint flag and turn off the WindowMaximizeButtonHint flag, I hope. Let me know if this works at all.
Edit:
As discovered by OP, the only call necessary for his desired outcome:
win.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)
but beware, since this will also remove the close button and potentially mess with other window flags.
This works perfectly:
MainWindow.setWindowFlags(QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMinimizeButtonHint)
you could set the maximumSize and minimumSize with the same values, it'll get to dissapear maximise button
This helped me:
Form.setMaximumSize(QtCore.QSize(width, height))
It would go here in your class:
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(328, 212)
Form.setMaximumSize(QtCore.QSize(352, 189))
This works in PyQT6:
MainWindow.setWindowFlags(QtCore.Qt.WindowType.CustomizeWindowHint | QtCore.Qt.WindowType.WindowCloseButtonHint | QtCore.Qt.WindowType.WindowMinimizeButtonHint)
Hope it's useful!
Related
My Current Project is to create a On Screen Keyboard for my personal usage with my personal functionality. I made gui and primary function in PyQt5 with Python. I managed to type the letter on button click with pyautogui.write() method. But the problem is, where I want to type there is no focus. suppose I want to write on chrome's address bar or any other input field on my monitor. when I click on button to type a letter, chrome lost focus. I want to set focus to the old window while press on any button. I searched on google about this but didn't found any answer. How can i set focus to old window? or is there any better way to type on focus lost state?
You should not try to "set the focus back", as it would be almost impossible to know what window had the focus before (and a new window might raise in the meantime). What you should actually do is to prevent your window to get focus at all, thus avoiding it to steal focus from the others.
In order to achieve this, you must set the appropriate window flag (or initialize the widget with it using the flags keyword argument), which for this is Qt.WindowDoesNotAcceptFocus.
Note that you might also want to set the Qt.WindowStaysOnTopHint in order to always keep your window above the others:
class MyKeyboard(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowFlags(
QtCore.Qt.WindowDoesNotAcceptFocus
| QtCore.Qt.WindowStaysOnTopHint
)
At the moment I have one Floatlayout in SHeditorMain, Inside the class SHeditormain i've declared a bunch of widgets (buttons, popups, labels, etc..) and used self.add_widget to add them.
Now i want to create a new window that opens up inside/over the FloatLayout and i can't seem to get it to works. All the examples i've seen so far regarding multiple windows is either using App as main class for the creation of widgets inside the layouts. Any suggestions or do i have to restructure the code?
class SHeditorMain(FloatLayout):
def __init__(self, **kwargs):
super(SHeditorMain, self).__init__(**kwargs)as
self.add_widget(blabla)
self.add_widget(blabla)
self.add_widget(blabla)
self.add_widget(blabla)
self.dbconnection = DBconnection()
#declare popups etc
def functionEvents(self, instance):
yaddayadda
def functionEvents(self, instance):
yaddayadda
def functionEvents(self, instance):
yaddayadda
class SHeditor(App):
def build(self):
self.root = SHeditorMain()
return self.root
Please read this answer about multiple "windows" and why it may not be desired. I can recommend you to have kivy window maximized and using ModalView as a pseudo-form that can be dragged and has some button that would close it. More control over everything, cleaner code, beginner friendly. Create a custom widget that inherits from ModalView and what it does is up to you.
You can place modals wherever you want them to be - look into popup source code in repo how the positions are set. You'll basically end up with a custom Popup that you can control without crippling the original widget.
Another way may be to use ScreenManager(or PageLayout, Carousel, xyz other widgets) which provide mobile-/presentation-like view. The sooner you get to kv language, the sooner you'll have less troubles to imagine that stuff out of pocket e.g. you see a fancy app, you can open kivy-designer or for more control/less fancy go for KivyCatalog and just type what you see that's how straightforward the kvlang is.
Example with Modals:(old attempt to create windows-like... something via Kivy = FloatLayout with Scatter(only drag enabled) as "windows")
Which leads me to the conclusion that if you think you need multiple windows or another window would be nice for whatever reason but you are not sure if it'd work or something - you actually don't and you are overcomplicating things, which steal your attention from the important parts of your code to UI.
(PS, I'd edit the answer mentioned at the top, but in that question user has a little bit more complicated problem)
How to change the button decoration with wxPython, generally when the button is clicked, a dotted lines appear on the button.. any way to make that button not show the dotted lines?
Thanks
Assuming you're running your program on Windows (you didn't say which OS, but dotted lines are used by Windows Classic look), the dotted lines are called the focus rect, and they appear to mark a button or widget as focused. They are a system setting, and your program is acting as it should - wxWidgets is meant to emulate the underlying OS default behaviour as closely as possible.
Update
I don't think you can change this behaviour from inside the program. I really doubt that wxWidgets has a setting somewhere for this, as it is OS-dependent and is the standard and correct behaviour for the Classic theme. But the focus rect is shown by default only on the Classic Look which few people use.
Try switching to Luna theme (the default on XP), and you'll see that the focus rect won't appear unless you start hitting Tab while your window is in focus. By the way, the focus rect is needed exactly for when you are switching the focus using the Tab key. You need to see where the focus is, after all. That way you know when you press Enter or Space, which button is going to be pressed. Not everyone uses only the mouse.
You can use a custom button, for instance wx.lib.buttons.GenButton which is in pure python so you can overwrite the look, feel etc.
This also has a method SetUseFocusIndicator to turn off the dotted focus indicator
How to suppress end user ability to edit/add/delete text in a Text widget? (Python v3.2.. and tkinter)
The point is to suppress only the ability to change/add/delete text but not to castrate other features. Perhaps a NoEdit Text widged would be a better name.
I've tried .text['state'] = 'disabled' and it works almost OK in Windows (it still allows user to select/copy text highlights the selection, page up/down and up/down buttons work. The only thing broken seems to be the cursor made invisible.)
But on MacIntosh everything is broken. No highlights, no select/copy,... UGH
Since Tkinter has practically no documentation in Python, I've searched and found some TCL advise, to derive a new class and suppress the insert and delete functions.
So, I've tried as so:
class roText(tk.Text):
def insert(self,*args,**kwargs):
print(" Hey - Im inside roText.insert")
pass
def delete(self,*args,**twargs):
pass
def pInsert(self,*args,**twargs):
super().insert(*args,**twargs)
Unfortunately it didn't work right. Apparently tkinter does not use those insert and delete functions when end user enters/deletes code. Perhaps those TCL insert/delete are something else, and I lost something in translation from TCL and Swahili. What functions does tkinter.Text use for end user editing text? Hopefully they are not internal...
So, is there a way to modify the Text widget to suppress only end user editing?
Is there a way to do it without diving inside and overriding internal Tkinter code, so the stuff doesn't get broken by next releases of Tkinter?
Looking at the Idle shell window, I see that they've managed to suppress edits (except for the last line). So there is a way. But what is it and how costly?
Sorry for bumping an old question, but I was searching for an answer to this question also and finally found a solution. The solution I found involves overriding the key bindings when the text widget has focus and is pretty simple. Found here.
To override the bindings of a widget there is a bind function where you pass a string of what is to be overridden and the new function you want it to call.
self.txtBox.bind("<Key>", self.empty)
Somewhere else in the class you'll need to define the function to handle the event.
def empty(self, event):
return "break"
By returning the string "break" the event handler knows to stop after your function, instead of continuing with the default action.
I hope this answers your question. Cheers.
The reason the disabled state doesn't seem to work on the Mac is because it turns off the binding that gives focus to the widget. Without focus, the highlighting on a Mac doesn't show up. If you set the state to disabled but then assign a binding to <ButtonPress-1> to explicitly set focus to the disabled text widget, you can then select and copy text and the highlighting will show.
As for the cursor disappearing... arguably, that's what's supposed to happen. The cursor tells the user "this is where text will get inserted". Since no text will get inserted, having that visual clue would be confusing to the user. What you could do instead, if it was really important, is to insert a small image wherever they click to simulate the cursor.
To answer your question about whether the widget actually uses the insert and delete methods: the methods on the actual underlying widget are what the default bindings use, so overriding them in a subclass has no effect. You would need to redo all the default bindings for that to work. It's doable, but a lot of work.
Unfortunately, this is one area where programming in Tcl really shines, because you can simply disable the insert and delete commands of the widget. Of course, you can do that directly in Tkinter also since ultimately it runs tcl code to do everything, but that would involve writing some tcl code which is not a very good solution from the perspective of a Python coder.
I think the best solution is to use the disabled state, then add in just enough bindings to do what you want.
Here's a simple example that works by explicitly setting focus on a mouse button click. With this code I'm able to click and swipe to select a region, or double- or triple-click to select words and lines:
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.text = tk.Text(width=40, height=20)
self.text.bind("<1>", self.set_focus)
self.text.insert("end", "\n".join(dir(tk.Tk)))
self.text.configure(state="disabled")
self.text.pack(fill="both", expand=True)
def set_focus(self, event):
'''Explicitly set focus, so user can select and copy text'''
self.text.focus_set()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
#BryanOakley It took me a while to test your suggestion since I have no Mac.
Unfortunately Mac implementation of Python is buggy.
I've added focus, ie my disable function which I call after creating a window and inserting text, now calls first:
self.txt['state'] = 'disabled'
and then
self.txt.focus_set()
Which is what I think you've suggested.
It "kind of" worked. Ie: when selecting text (click and drag or double-click) highlighting works most of the time. Python must have some bad memory references or such bugs: Sometimes highlighting doesn't work at first, then it starts working (in the same window) after more clicking. Sometimes when program is invoked it works right of the bat. Sometimes selecting with Shift-rightArrow key will work but selecting with the mouse will not. Then starts working again. Or it will work fine in one window but not in another one (both of the same class), then starts working in all windows...etc...
The good thing is that adding focus did not affect badly Windows (ie all works fine as without focus.
I guess at this point I will just hope that future/next release of Python for Mac will fix those bugs..
BTW, it seems that Mac is a bit of an orphan for Python. Implementation is much uglier then for Windows. I mean the fonts look worse, the buttons, etc.. Or it could be due to different screen resolutions and Python ports that poorly account for those. Not sure
Anyway. Thank you for your help and suggestion to use focus for Mac.
I would like to have my pyqt aplication have tabs in the menu bar like Google Chrome :)
Any suggestions or a simple example on how to do it?
I did find these relevant link:
- http://ivan.fomentgroup.org/blog/2009/03/29/instant-chrome/
You have to use the Qt.FramelessWindowHint for that, and then create your own Max, Min, Close buttons as Widgets and add them there. I have a good working toolkit for these types of softwares: http://traipse.assembla.com/spaces/ghostqt
In your case you should reclass the resizeEvent so you can change the flags. If the window is maximized you will not need to worry about moving it around, but if it is not maximized you can remove the Qt.FramelessWindowHint flag and get your title bar back; just like Chrome does.
Is that what you are looking for?
If I understand correctly, just create a QWindow that contains a QTabBar widget(and not a QMenuBar, or simply use a QTabWidget as your main program widget.
you need to do the following:
remove window border (FramelessWindowHint)
Implement your own window moving and resizing code
Insert tabbar on the top, and add buttons for close etc. to it (or create a frame that will contain the tabbar and buttons)
And that's all that was done in Webbie (the link you provided) :)