NSPopover positions incorrectly when NSWindow frame is programmatically changed - nswindow

I have a button in an NSWindow that brings up an NSPopover with:
popover = NSPopover()
popover?.behavior = .applicationDefined
popover?.contentViewController = self
let myDelegate = MyDelegate()
myDelegate.controller = self
popover?.delegate = myDelegate
popover?.show(relativeTo: hostingButton.bounds, of: hostingButton.superview!, preferredEdge: .minY)
This works great and I can drag the window around and resize it while the popover is open with zero problems.
The window, however, displays dynamic content and I have an option to keep it "compact" so to use the minimum height necessary for all of the current content to be shown.
When my code sets the NSWindow's frame with window.setFrame(newFrame, display: true), the popover moves to the other side of the screen. Its vertical alignment is perfect and matches the new window height, but its horizontal position is completely off.
The horizontal positioning on the Screen appears to be matching the x coordinate of the hostingButton within its superview, i.e. it sure looks like popover is using the x coordinate from the button's frame as a screen coordinate!?
Am I doing something wrong?
Is there a way of asking the popover, its hosting view, its superview, or its window to have another go at the positioning?
If not is there a way that I can manually move the popover window to the right place?
Any help would be much appreciated!

Related

How to restrict growth (size) of layout in Qt Designer?

When I maximize my window, I want to restrict a vertical layout (and the entire row below it also) so that it has a specific size (lets say a width of 200). How can I achieve this? Below is what I get now. The buttons are stretched too far. I want them to keep a width of 200.
To stop the buttons stretching, use the following steps in Qt Designer:
click on scrollArea in the Object Inspector
click on Break Layout on the toolbar
click on scrollArea in the Object Inspector
click on Lay Out in a Grid on the toolbar
click on scrollAreaWidgetContents in the Object Inspector
scroll down to the bottom of the Property Editor
change layoutColumnStretch to 0,1
These steps should remove an empty column from the scroll-area grid-layout, and make the second column stretch to take up the available space when the window is resized.
You just need to restrict the maximum width of all widgets (in this case the buttons) within the layouts of this grid column to the expected size, else they'll just keep expanding. You may also have to fiddle the horizontal size policy; I seem to remember that buttons were a bit tricky in this regard (or was that the height?), but can't test it right now.
The layout size contraint you tried only applies to the layout's direct parent widget, if it has one, which isn't the case for the vertical layouts here.

How to setup views in game maker studio?

How do I get rid of these black bars?
I've looked around and people say how to get rid of them but don't show how its done. This is what I have in my character Creation event.
`///Camera
view_wview[1]=611;//set wiew width
view_hview[1]=611;//set view height
view_enabled[1] = true;//enable view
view_visible[1] = true;//make visible
view_hborder[1]=1920;//set horizontal border for object
view_vborder[1]=1080;//set vertical border
view_object[1]=obj_Medic;//set object to follow
`
You could widen your view to fit your screen or set your game to fit the screen in the display options menu as shown:
The stretching may cause distortions as you can see from my example, an unfinished project I made a while back (a RoTMG simulator).
Window:
Stretched Fullscreen:

How do I find the part of a NSScrollView's documentView that's not beneath a window's toolbar?

I have a very simple setup. It's a single window with a toolbar, completely filled with a NSScrollView. The window is setup as follows:
window.styleMask = [.titled, .resizable, .closable, .fullSizeContentView]
window.titleVisibility = .hidden
This looks pretty gorgeous! However, I need to change how the content of the document view behaves as its frame changes. The problem is that docuentView.visibleRect reports that the minY is 0.0 until it hits the top of the window, not the bottom of the toolbar! So some of my custom drawing and behavior is cut off, and that is not so gorgeous.
How do I find the actually-usable rect of that document view, which excludes the part of it beneath the toolbar?
There is a property on the window called contentLayoutRect, which represents the portion of the window content that is visible (using non-flipped coordinates). You can use this to position the content view and rest assured that this will still work if Apple decides some other edge of the window becomes obscured.

How do i resize the contents of a QScrollArea as more widgets are placed inside

I have a QScrollArea Widget, which starts empty;
It has a vertical layout, with a QGridLayout, and a vertical spacer to keep it at the top, and prevent it from stretching over the whole scroll area;
Elsewhere in the program, there is a QTextEdit, which when changed, has its contents scanned for "species" elements, and then they are added to the QGridLayout. Any species elements which have been removed are removed too. This bit works;
I have turned the vertical scrollbar on all the time, so that when it appears it does not sit on top of the other stuff in there. Note that the scroll bar is larger than the scroll box already though, despite not needing to be.
This is the problem. The scroll area seems to be preset, and i cannot change it. If i add more rows to the QGridLayout, the scroll area doesn't increase in size.
Instead, it stays the same size, and squeezes the QGridLayout, making it look ugly (at first);
And then after adding even more it becomes unusable;
Note that again, the scroll bar is still the same size as in previous images. The first two images are from Qt Designer, the subsequent 3 are from the program running.
If I resize the window so that the QScrollArea grows, then I see this:
Indicating that there's some layout inside the scroll area that is not resizing properly.
My question is; what do I need to do to make the scrollable area of the widget resize dynamically as I add and remove from the QGridLayout?
If you're coming here from Google and not having luck with the accepted answer, that's because you're missing the other secret invocation: QScrollArea::setWidget. You must create and explicitly identify a single widget which is to be scrolled. It's not enough to just add the item as a child! Adding multiple items directly to the ScrollArea will also not work.
This script demonstrates a simple working example of QScrollArea:
from PySide.QtGui import *
app = QApplication([])
scroll = QScrollArea()
scroll.setWidgetResizable(True) # CRITICAL
inner = QFrame(scroll)
inner.setLayout(QVBoxLayout())
scroll.setWidget(inner) # CRITICAL
for i in range(40):
b = QPushButton(inner)
b.setText(str(i))
inner.layout().addWidget(b)
scroll.show()
app.exec_()
The documentation provide an answer :
widgetResizable : bool
This property holds whether the scroll area should resize the view widget.
If this property is set to false (the default), the scroll area honors the size of its widget.
Set it to true.
Why don't you use a QListView for your rows, it will manage all the issues for you? Just make sure that after you add it you click on the Class (top right window of designer) and assign a layout or it wont expand properly.
I use a QLIstWidget inside a QScrollArea to make a scrollable image list
Try this for adding other objects to the list, this is how I add an image to the list.
QImage& qim = myclass.getQTImage();
QImage iconImage = copyImageToSquareRegion(qim, ui->display_image->palette().color(QWidget::backgroundRole()));
QListWidgetItem* pItem = new QListWidgetItem(QIcon(QPixmap::fromImage(iconImage)), NULL);
pItem->setData(Qt::UserRole, "thumb" + QString::number(ui->ImageThumbList->count())); // probably not necessary for you
QString strTooltip = "a tooltip"
pItem->setToolTip(strTooltip);
ui->ImageThumbList->addItem(pItem);
Update on Artfunkel's answer:
Here's a PySide6 demo that uses a "Populate" button to run the for loop adding items to the scroll area. Each button will also delete itself when clicked.
from PySide6.QtWidgets import *
app = QApplication([])
scroll = QScrollArea()
scroll.setWidgetResizable(True) # CRITICAL
inner = QFrame(scroll)
inner.setLayout(QVBoxLayout())
scroll.setWidget(inner) # CRITICAL
def on_remove_widget(button):
button.deleteLater()
def populate():
for i in range(40):
b = QPushButton(inner)
b.setText(str(i))
b.clicked.connect(b.deleteLater)
inner.layout().addWidget(b)
b = QPushButton(inner)
b.setText("Populate")
b.clicked.connect(populate)
inner.layout().addWidget(b)
scroll.show()
app.exec()

qt unexpandable layout?

Ok, here is my problem:
I have a vertical layout which contains a QPlainTextEdit and a horizontal layout (containing 2 QPushButtons) below the text edit.
The vertical layout is just a part of GUI, and gets resized depending on screen resolution. Btw. it is a mobile app, so I don't have a lot of space on screen.
Push buttons have some text which is dynamically set, I don't know it from the beginning to code it manually.
My problem occurs when the text in push buttons is big, and my whole vertical layout is expanded to fit the buttons.
How can I make the vertical layout unexpandable? note, that this is different from "fixed" because of different screen resoulutions.
I'd just like the clip the buttons if they do not fit, but keep the layout width untouched.
Anyway to do this?
You'll need to set the maximum width for the buttons, not the layout, which is only widening to fit the wider buttons. Check out the docs on QPushButton and look for QWidget inherited functions called setMaximumSize or setMaximumWidth.
You can always GetWidth() on the button when it is an appropriate size, then setMaximumWidth using that value since you wouldn't ordinarily know this. Pick an appropriate default text size/val and use that to create your "dynamic" default since this is going on screens of varying size.

Resources