Qt: get all children within region of the parent - python

This is my first question ever so bear with me!
Currently in my program, I have a parent widget which acts as a canvas. The user can add or remove widgets to the parent at run-time. Those widgets are then given an absolute position, that is, they are not positioned by a layout. Once added, a widget can be moved around arbitrarily by the user.
I want the user to be able to select a group of widgets by dragging a box around them. I have already coded the part that displays the rectangle while the user is dragging. Now, I want to be able to retrieve all the widgets within that rectangle (region).
I am aware of the findChild() and findChildren() functions, and they indeed do return the children as they are supposed to. But what I'd really need is a way to limit the search to the boundaries of the region since there will most-likely be quite a lot of widgets within the 'canvas'. (There could be thousands of widgets spread over a very large area due to the nature of what I'm doing!)
Here is my question: What would be my best option? Should I just go ahead and use findChildren() and loop through the list to find the children within the region manually. Or should I loop through all the pixels within the region using findChild(x, y)? Or perhaps there is an even simpler solution that would speed up the process? Something along the lines of findChildren(x, y, width, height)?
Hopefully my question made sense. I tried to explain things as best as I could. Thanks!

If you had used QGraphicsScene instead of rolling your own, you could have used the items(..) methods to very efficiently find your children in a particular area.
It's only possible in QGraphicsScene because it uses a BSP spatial acceleration structure, so if you cannot migrate to QGraphicsScene in a reasonable amount of time - you are going to have write your own. It's not as hard as it sounds, I've written numerous bounding volume hierarchy structures and they're quite straightforward.

Related

In wxpython, how to set position of objects within a wxScrolledWindow

I am writing a kicad plugin, and I need to create a GUI for this plugin. Because kicad uses wxpython, that is what I am using.
I have already figured out that placing my ui items using the layout sizers just isn't gonna give me the control I need to create the window I want. I know I can set the position of elements, and have been using that to create the ui I need.
The problem however, is that my window gets bigger than what would be reasonable (in some situations). Therefore I want to make it scrollable.
I have been playing around with wxformbuilder, and I found the wxScrolledWindow. That got me this far:
This is roughly what I want, except, when you want to place stuff within the scrolledWindow, you have to place one of the "sizers" in it (as far as I can tell at least), in which you place your buttons. The problem with that is, that, to my knowledge, setting the position of buttons in any of the sizers just has no effect at all.
So, my question is: how do I achieve this effect? and, is this even possible?
edit:
As an example of what I am trying to put within the scrolledwindow, this is a rough version of the ui I want to create (and want to be scrollable). (I want to eventually have, probably an icon button above each of the checkbox columns to indicate what they are for).
The final result would need to look something like this (the white squares being small images / buttons, also, in reality being not on the window bar,but in its own not scrolling section):
An example of something I wasn't able to achieve using sizers is, getting those checkboxes so close together, without making them appear off center. Different widgets seem to have different sizes, and checkboxes without border are especially small, so they end up appearing off center, example:
Also, those images above each column of checkboxes, which don't scroll, need to line up with the X coordinates of those scrolling checkboxes, which also seems very non trivial. Though also really hard to get right if I could give everything exact coords, so I might need to give up on that specific idea of making those not scrollable.

How to drag objects around in a Gtk.Fixed widget using mouse events?

I have a custom object(a small circle) placed at some point inside a Gtk.Fixed() widget .Is there a way to drag this object around using the mouse. I am not able to map the Mouse Press/Release/Motion events to make this work.
I would prefer solution in Python using PyGobject but any other language will do also be fine if explanation is provided
More Details:
I am trying to make a font editor where these objects I mentioned above will be the control points of the bezier curves in the Glyph outlines
Here is an image of the concept design:
https://github.com/sugarlabs/edit-fonts-activity/blob/gh-pages/files/img/wireframe_concept_01_first_prototype.svg
I need to able to move the points shown to edit the outline of the letter shown
GtkFixed is not designed to do drawing work. It's made to locate widgets (such as buttons and such) on a fixed grid (รก la Windows).
If you would like to move elements of a drawing, have a look at eg. GooCanvas. Each element on a goocanvas can have events connected, which can then be used to move it around. You can even use CanvasGroup to group primitives (circle, rectangle etc), and move them together (even change other properties such as color, linewidth). The toolbox actually contains curves etc. It's easy to create a 'handle' using a small rectangle.
Here's an example of a simple goocanvas program, and you can find download links, references manuals and other useful stuff here.
I don't know if this is a tool you need, or just a learning exercise. If the former, then do have a look at FontForge, an open source font editor, and incredibly versatile.

Stacking QGraphicsWidgets side by side

I've created a widget that uses the QGraphicsFramework to draw items to a canvas. Currently, I use one QGraphicsScene to keep track of my items and a QGraphicsView to visualize the items in the scene. I am using PyQt, but this is really more of a general Qt question.
This is what I have. It's one QGrapicsView and one QGraphicsScene.
What I want, where it's all drawn on one QGraphicsView, with three QGrapicsWidgets.
The first problem is that I don't know Qt that well so I am not sure if I understand the concepts correctly. It is my understanding that a QGraphicsWidget inherits from the QGraphicsItem so that I can add many of them to the same scene while still being able to handle all the events internally.
The problem with that is that the items inside each of these widgets need their own grid because items need to be at some given coordinates and have transforms inside the widget, etc. I am not sure how this could function, since there doesn't seem to be any such QGraphicsLayout that would allow this. This also kind of means each widget would need its own QGraphicsScene. I am not sure how to achieve this.
Can a QGraphicsWidget even have its own scene or does it have to access the shared main scene? If it had to access the shared scene, then each widget would need to be aware of where it was, which seems silly.
I don't need an implementation, just a clarification of how I would go about achieving this with QGraphicsWidgets. Or is my understanding of the QGraphicsWidget completely off?

How can I make the icons in an IconView spread out evenly?

I have a gtk.IconView with several icons in it. Sometimes I will resize the window to see more icons. When I do this, the extra space generated isn't distributed evenly between all the columns. Instead, it all gets put on the right until there's enough space for a new column.
I'm not seeing anything in the documentation that would let me do this automatically. Do I need to check for resize signals and then manually set the column and row spacings? If so, which resize signal do I use.
Here's a picture of what I mean. I've marked the extra space in red.
This is what I'd like to see (of course, with the gaps actually evenly spaced, unlike my poor MS Paint job).
We have encountered that problem in Ubuntu Accomplishments Viewer, and as we managed to solve it, I'll present our solution.
The trick is to place the GtkIconView in a GtkScrolledWindow, and set it's hscrollbar_policy to "always". Then, a check-resize signal has to be used, to react when the user resizes the window (note that it must be checked if the size has changed, for the signal is emitted also when e.g. the window is dragged around). When the size changes, the model used by GtkIconView has to be cleared and recreated, as this triggers GtkIconView properly reallocating the newly gained space (or shrinking). Also, as the result the horizontal scrollbar will never be seen, as the GtkIconView uses exactly that much space as the GtkScrolledWindow uses.
Yeap, it seems after a very fat look that you will need to do that on your own. And regardeing the signal, I'd check for GtkContainer::check-resize.
Use the event size_allocate.
I defined my class :
class toto(Gtk.IconView):
def __init__(self):
super(toto,self).__init__()
self.connect("size_allocate",self.resize)
self.set_columns(4)
Then I modify the number of working columns
def resize(self,_iv,_rect):
print("X",rect.x)
print("Y",rect.y)
print("W",rect.width)
print("H",rect.height)
# calculate number of columns, let's say 3
_cols=3
self.set_columns(_cols)
Seems working for me

Game map from Code

It's a long one so you might want to get that cup of tea/coffee you've been holding off on ;)
I run a game called World of Arl, it's a turn based strategy game akin to Risk or Diplomacy. Each player has a set of cities, armies and whatnot. The question revolves around the display of these things. Currently the map is created using a background image with CSS positioning of team icons on top of that to represent cities. You can see how it looks here: WoA Map
The background image for the map is located here: Map background and created in Omnigraffle. It's not designed to draw maps but I'm hopelessly incompetent with photoshop and this works for my purposes just fine.
The problem comes that I want to perform such fun things as pathfinding and for that I need to have the map somehow stored in code. I have tried using PIL, I have looked at incorporating it with Blender, I tried going "old school" and creating tiles as from many older games and finally I tried to use SVG. I say this so you can see clearly that it's not through lack of trying that I have this problem ;)
I want to be able to store the map layout in code and both create an image from it and use it for things such as pathfinding. I'm using Python but I suspect that most answers will be generic. The cities other such things are stored already and easily drawn on, I want to store the layout of the landmass and features on the landmass.
As for pathfinding, each type of terrain has a movement cost and when the map is stored as just an image I can't access the terrain of a given area. In addition to pathfinding I wish to be able to know the terrain for various things related to the game, cities in mountains produce stone for example.
Is there a good way to do this and what terms should I have used in Google because the terms I tried all came up with unrelated stuff (mapping being something completely different most of the time).
Edit 2:
Armies can be placed anywhere on the map as can cities, well, anywhere but in the water where they'd sink, drown and probably complain (in that order).
After chatting to somebody on MSN who made me go over the really minute details and who has a better understanding of the game (owing to the fact that he's played it) it's occurring to me that tiles are the way to go but not the way I had initially thought. I put the bitmap down as it is now but also have a data layer of tiles, each tile has a given terrain type and thus pathfinding and suchlike can be done on it yet at the same time I still render using Omnigraffle which works pretty well.
I will be making an editor for this as suggested by Adam Smith. I don't know that graphs will be relevant Xynth but I've not had a chance to look into them fully yet.
I really appreciate all those that answered my question, thanks.
I'd store a game map in code as a graph.
Each node would represent a country/city and each edge would represent adjacency. Once you have a map like that, I'm sure you can find many resources on AI (pathfinding, strategy, etc.) online.
If you want to be able to build an image of the map programattically, consider adding an (x, y) coordinate and an image for each node. That way you can display all of the images at the given coordinates to build up a map view.
The key thing to realize here is that you don't have to use just one map. You can use two maps:
The one you already have which is drawn on screen
A hidden map which isn't drawn but which is used for path finding, collision detection etc.
The natural next question then is where does this second map come from? Easy, you create your own tool which can load your first map, and display it. Your tool will then let you draw boundaries around you islands and place markers at your cities. These markers and boundaries (simple polygons e.g.) are stored as your second map and is used in your code to do path finding etc.
In fact you can have your tool emit python code which creates the graphs and polygons so that you don't have to load any data yourself.
I am just basically telling you to make a level editor. It isn't very hard to do. You just need some buttons to click on to define what you are adding. e.g. if you are adding a polygon. Then you can just add each mouse coordinate to an array each time you click on your mouse if you have toggled your add polygon button. You can have another button for adding cities so that each time you click on the map you will record that coordinate for the city and possibly a corresponding name that you can provide in a text box.
You're going to have to translate your map into an abstract representation of some kind. Either a grid (hex or square) or a graph as xynth suggests. That's the only way you're going to be able to apply things like pathfinding algorithms to it.
IMO, the map should be rendered in the first place instead of being a bitmap. What you should be doing is to have separate objects each knowing its dimensions clearly such as a generic Area class and classes like City, Town etc derived from this class. Your objects should have all the information about their location, their terrain etc and should be rendered/painted etc. This way you will have exact knowledge of where everything lies.
Another option is to keep the bitmap as it is and keep this information in your objects as their data. By doing this the objects won't have a draw function but they will have precise information of their placement etc. This is sort of duplicating the data but if you want to go with the bitmap option, I can't think of any other way.
If you just want to do e.g. 2D hit-testing on the map, then storing it yourself is fine. There are a few possibilities for how you can store the information:
A polygon per island
Representing each island as union of a list rectangles (commonly used by windowing systems)
Creating a special (maybe greyscale) bitmap of the map which uses a unique solid colour for each island
Something more complex (perhaps whatever Omnigiraffe's internal representation is)
Asuming the map is fixed (not created on the fly) its "correct" to use a bitmap as graphical representation - you want to make it as pretty as possible.
For any game related features such as pathfinding or whatever fancy stuff you want to add you should add adequate data structures, even if that means some data is redundant.
E.g. describe the boundaries of the isles as polygon splines (either manually or automatically created from the bitmap, thats up to you and how much effort you want to spend and is needed to get the functionality you want).
To sum it up: create data structures matching the problems you have to solve, the bitmap is fine for looks but avoid doing pathfining or other stuff on it.

Categories