I created a sketchUp plugin that draws a wall (with lenght, width and height).
Now I would like to insert a "window" in that wall (fixed length, width and height, depending on the wall). How can I:
Create but not yet draw the group containing the window. Link it to the current mouse position
Constrain the current mouse position to the front plane of the wall I drew before
When the user clicks, the window is inserted and the group is shown
The easy way to do it, that doesn't fulfill your request 100% - but do use existing SketchUp conventions, is to create a component definition and then use Model.place_component to activate SketchUp's native tool to position a new component instance.
In order to fulfill your question 100%:
A Group is an instance. You cannot create one and not place it in the model. You can create it in step 3 when the user clicks. (Though, a window sounds like a candidate for a component since you usually have multiple copies of the same window type.)
You cannot constrain the mouse cursor itself, but if you implement a custom Tool and make use of the InputPoint class you can selectively determine what is a valid insertion point when the user clicks. You can also draw virtual lines and polygons to the viewport to give a preview of your window.
Profit!
Related
So I currently have got a custom widget, and I want to add them to the main window after clicking a button. I would like to add them all to one fixed position first and then I will be able to drag them wherever I like. I am able to create and display these custom widgets with help of QHBoxLayout or QVBoxLayout, but in this case they will not be in the same position after I create them. Any help will be appreciated!
As the names suggest, the QLayout classes manage the position and geometry of the items added to them. You cannot move (eg. drag) an item out of a layout w/out first removing it from the layout (QLayout::removeItem() and derivatives). For example when you drag a toolbar or dock widget out of a QMainWindow it goes through all sorts of machinations to remove it from the MW layout, change the widget's window flags, remember the old position in the layout, and so on. And the reverse to dock it again.
To do what you describe (drag widgets arbitrarily around a window) you would need to not use a QLayout and position the widgets manually by specifying a QWidget::setGeometry() for example. After initial position, and assuming the user has some way to grab the widget (title bar or drag handle you made, etc), you'll probably still need to manage their positions, for example if the main window is resized (if you care about keeping them contained). Essentially you'd have a bunch of separate widgets acting as individual windows and probably need some way to keep track of them.
I don't know what kind of widgets you're talking about, but one option may be a QMdiArea which lets the user drag windowed widgets around, tabify them, save/restore state, and so on.
For more flexibility you could also look into the Qt Graphics Framework. The graphics scene has a lot of features for user-movable items/widgets, keeping track of them, and so on. It is probably the most flexible method overall, and you can also use regular QWidgets inside a graphics scene.
A couple other Q/A about arbitrarily positioning widgets (I'm sure there are more to be found):
QPushButton alignment on top another widget
How to keep Push Buttons constant in relative to change of Label Size in PyQt4
Like the qmmp(Qt) music player ui design, these two or three windows are in fact in the same window, because there is only a dock icon, and these windows can move together and attach to each other.
I read the source code, it seems use QDockWidget. But I really don't know the details how to get it.
When you manually move the secondary window, in this case - the playlist, you check where the manual move ends, and if it is on the edges of the primary window, you glue it by simply binding its position to the position and dimensions of the primary window.
Since the window position and dimensions are properties, they have notification signals, so you can connect those to a function that automatically moves the glued window.
And finally, when you attempt to manually move the secondary window, you un-glue by disconnecting.
You can easily support offset gluing instead of a purely horizontal or vertical one, by calculating and storing the positioning offset and applying it on every primary window move.
If the drop happens within a given threshold of the primary window you can snap to the edge. If you factor in the mouse position relative to the dragged window, you can even snap particular edges together.
I am trying to create a specific solution for weeks now and I have tried many things but I am just not sure if it is possible at all to achieve. I need your opinions and point me in direction o a correct approach. Following what I am trying to create:
Initially there is a tile layout in which a certain number of cards (say 12) are placed in 4x3 grid:
Now, if user clicks on a tile (Box 3), the state changes to following:
Selected tile is expanded and other tiles get aligned one below another on the right side:
Challenge is that I want to create a transition from every tile's initial state to the state where every tile is aligned one below another on the right. At the same time, when a tile is clicked it is expanded in place.
Note - there are no sudden change in positions, no reload of page and preferably no JS (I wanted to write a CSS-only solution). Everything smoothly animates to new position. From the second screen if a different tile is selected (from right), then the expanded item will shrink and go in to the right hand stack while the selected item will expand and take place of the currently expanded (B3).
If you could just point me to correct direction it would be great help.
thanks.
You should check css flexbox.
Using the "order" proprety, you could asign order of every box from 2 to 8,
and each time a box is selected, you change it's order to 1 and you also change its size and colour.
However, I don't think you can use 'click' actions with css only.
I would recommend using JS for what you are trying to achieve.
Hope it helps
I'm working on a simple widget system, and I'm implementing some containers right now.
Here's the situation I find myself in:
I have a Widget base class, a Container class, which is a widget that can contain other widgets, and several widget sub classes like Button.
I have two types of container: Container itself, which positions children absolutely, and Box, which will stack widgets next to each other, either horizontally or vertically.
Each widget draws itself at x=0, y=0. Therefore, containers need to add an offset to the drawing context before the widgets are told to draw themselves.
Each widget does its own hit testing based on its x/y position.
So far, it works fine. But it falls apart now that I'm implementing Box: What I do is that I overwrite the drawfunction inherited from Container to draw them all in next to each other, instead of based on their x/y position. Quite simple.
But event handling is totally off now, as the widget's x/y position has become meaningless.
I think I have two options:
Have the widget do hit testing at position x=0, y=0, like drawing. Then recalculate the mouse position to match that in Container.
Make each layout set x/y for its children, and make children draw themselves at their x/y position again. No more offsets for the drawing context
The first one is a bit ugly, I think. The second one is pretty complicated to implement, since I need to react to position changes in widgets.
How to other widget systems like Qt, Gtk and wxWidgets generally tackle this? I've looked at the source of some of these, but can't quite figure that out, it's too sophisticated. I don't have any resizing or packing issues to consider.
You are trying to implement your own layout system. You should expect it to be difficult.
I would advise against the first method. The x,y coordinates of a widget are not only used by the widgets themselves, but by anyone outside of the container who wants to do something with the widget.
The second solution is what I've chosen to implement custom widgets made of several smaller widgets and it's not that hard to put together if you don't want too many features.
Just get the widgets when they are added to your container, set their position to the current free spot, and move on to the next.
Hi i'm trying to get a photoshop-like behaviour for my QGraphicsScene
The grid in the background should not resize with the call of scale. And I must be able to save the picture with QPixmap::grabWidget(view) but without the background grid. I can probably do it with removing the background layer just before saving the picture, but i'm not sure if its cleanest way to do it.
Any ideas ?
thx.
Question 1
The grid in the background should not resize with the call of scale.
Use the QGraphicsItem::ItemIgnoresTransformations flag.
The item ignores inherited transformations (i.e., its position is
still anchored to its parent, but the parent or view rotation, zoom or
shear transformations are ignored). This flag is useful for keeping
text label items horizontal and unscaled, so they will still be
readable if the view is transformed. When set, the item's view
geometry and scene geometry will be maintained separately.
In order to set this flag use the setFlag function when creating the grid item.
Question 2
I must be able to save the picture with QPixmap::grabWidget(view) but without the
background grid.
Call the hide function on the grid item before calling the grabWidget. After you have grabbed it you show it again by calling the show function.