I am building an editor using C++/Qt which has a click-and-drag feel to it. The behavour is similar to schematic editors (Eagle, KiCAD, etc), Microsoft Visio, or other programs where you drag objects from a toolbar into a central editing area.
My problem is that when the user clicks inside the custom widget I want to be able to select the instance of the box-like object and manipulate it. There will also be lines connecting the boxes together. However, I can't decide on an efficient method for selecting those objects.
I have two main thoughts on how to do the programming for this: The first is that the widget which is drawing the entire editor would simply encapsulate every one of the instances of the box. The other is to have each instance of the box (which is in my Model) carry with it an instance of a QWidget which would handle rendering the box (which would be in my View...but it would end up being strongly attached to the model). As for the lines connecting them, since they don't have a square bounding boxes they will have to be rendered by the containing widget.
So here is the summary of how I see this being done:
The editor widget turns into a container which holds the widgets and the widgets process their own click events. The potential issues here are that I don't know how to make the custom widget turn into a layout which lets click-and-drag functionality.
The editor widget takes care of all the rendering and processes the mouse clicks (the easier way in that I don't have to worry about layout...its just selecting the instances efficiently that I don't know what would be best).
So, now that there is a bit of background, for the 2nd method I plan on having each box-like instance having a bounding rectangle and the lines being represented by 3-4 pixel wide bounding rectangle segments (they are at 90 degree angles). I could iterate through every single box and line, but that seems really inefficient.
The big question: Is there some sort of data structure I can hold rectangles in and link them to widgets (or anything else for that matter) and then give it two coordinates (such as mouse coordinates) and have it spit me out the bounding box or linked object that those coordinates are inside of?
It sounds like your real question is about finding a good way to implement your editor, not the specifics of rectangle intersection performance.
You may be interested in Qt's "Diagram Scene" example project, which demonstrates the QGraphicsScene API. It sounds like a good fit for the scenario you describe. (The full source for the example ships with Qt.)
The best part is that you still don't have to implement hit testing yourself, because the API already provides what you are looking for (e.g., QGraphicsScene::itemAt()).
It's worth noting that internally, QGraphicsScene uses a simple iterative method to perform hit tests. As others have pointed out, this isn't going to be a serious bottleneck unless your scenes have a lot of individual items.
Related
As an example, imagine a complex snap operation, consisting of two active snappings in a context. Here two indicators on the second image show, that we are snapping perpendicularly and that we are snapping to any point of the line. When we drag out from the snapping intersection, we are not snapping to a point anymore, but we are still snapping perpendicularly to the reference line. For such and similar situations I would like to extend the cursor with different indicators, based on the context, like on these images.
Is it possible in MFC? Or otherwise in a Windows application?
Extending the cursor is not supported, you can only load one. So the best approach is to create all the cursors as .CUR files and then load them as needed.
Cursors can be created programmatically in Win32. The CreateCursor() function creates a cursor taking its dimensions, its hot spot and its AND (black) and XOR (invert) masks as parameters. Therefore you can create or load the basic pointer cursor masks and then add the indicators (either draw them using GDI, if they are simple, or load them from resources), creating the additional cursors you may need. I think it's a quite heavy job to do all these on the fly, so it would best to create all possible indicators during initialization.
The CreateCursor() function seems to create only monochrome cursors, maybe the CreateIconIndirect() function can create color cursors. Also take a look into this Win32 documentation topic: Using Cursors.
Of course this is quite an amount of work. You decide if it's worth or not...
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I'm designing a simple GUI framework from scratch as a project, using OpenGL and nothing else external and need some advice on how I might implement user interaction.
Basically, I've a base class GUIItem from which all elements inherit. This gives each item some basic variables such as position, a vector to contain child elements as well as some basic functions for mouse movement and clicking.
All elements are setup as above, with their relevant member variables.
What I'm struggling with is how to implement user interaction properly. In my window manager I would create a new instance of an item, say GUIButton and call it button1. The window manager would, upon a click occurring, iterate through its list of elements and any child elements they may have, calculating a rectangular area around the object based on its coordinates, height and width, then running any "on click" function associated with said item, like change the value of textlabel1.
Firstly, is there a better way to do this calculation? It would work for rectangular elements but spherical objects and others would have a much larger erroneous area which could be clicked. Ideally I would check pixels but I've no real idea how that would be achieved. I've heard about but never used GLUT (my project only allows use of this for handling mouse/keyboard interaction though). Does GLUT provide anything to assist in this case?
My main issue is with handling what would occur when an "On click" event actually occurred. At the moment GUIButton for example, has an "On click" function built in, so as far as I can see, I'd have to do something like make it a virtual function, meaning that each new button I created would have to have its own class just to overwrite the "on click" function and each instance of a button would be an instance of a unique class that simply inherited off of GUIButton. This seems messy to me, as I've no idea where I would store all those classes, and it seems a lot of extra code. Would I be creating a button1.cpp and button1.h file?
Any advice on this really would be welcome as I'm new to C++, OpenGL and it's the first time I've been exposed to GUI programming and there's not a lot to go on when an existing GUI framework is the usual choice.
if you want something stupidly simple and fast then you could:
create shadow screen buffer containing ID/index/pointer instead of color
pre-render this buffer
Just render each of your visual component to it but instead coloring/texturing just fill in the ID/index/pointer of rendered component. Do not forget to clear this with some NULL first ... After this you should have mask of your components. You need to do this just once ...
On mouse events
you simply convert mouse coordinates to the shadow screen space and pick the value. If it is NULL then you clicked or whatever on empty area. If it contains ID instead update or call the callbacks for component ID. if you have a list of all components then ID can be the list index, otherwise use its actual pointer or encode in style (component_type, component_index). As you can see this is pretty fast O(1) item selection no matter how many components you have ... The shadow screen can have different resolution then your actual screen (to preserve memory).
This have pixel perfect mouse selection accuracy no matter the shape of your components without the need for nested component search loops.
[Notes]
As I did this stuff here are some hints:
create a window class containing configuration of your components for single screen. Programs have usually more screens with different set of components and doing dynamically the screens over and over again just because you switch page/screen sucks.
use separate list of components one list per component type.
create IDE editor for your windows see drag & drop example in C++ it might get handy for this. Add get,set functions controlled by string/enum or flag to easy obtain/change properties to make Object Inspector possible. Also this is how mine IDE looks like:
The window is saved from IDE directly as C++ code I can just copy to my App. This is the above example without the knob (forgot to save it):
//---------------------------------------------------------------------------
// OpenGL VCL window beg: win
win.grid.allocate(0);
win.grid.num=0;
win.scale.allocate(0);
win.scale.num=0;
win.button.allocate(0);
win.button.num=0;
win.knob.allocate(0);
win.knob.num=0;
win.scrollbar.allocate(3);
win.scrollbar.num=3;
win.scrollbar[0].x0=200.0;
win.scrollbar[0].y0=19.0;
win.scrollbar[0].xs=256.0;
win.scrollbar[0].ys=16.0;
win.scrollbar[0].fxs=8.0;
win.scrollbar[0].fys=19.0;
win.scrollbar[0].name="_vcl_scrollbar0";
win.scrollbar[0].hint="";
win.scrollbar[0].min=0.000;
win.scrollbar[0].max=1.000;
win.scrollbar[0].pos=0.000;
win.scrollbar[0].dpos=0.100;
win.scrollbar[0].horizontal=1;
win.scrollbar[0].style=0;
win.scrollbar[0].resize();
win.scrollbar[1].x0=200.0;
win.scrollbar[1].y0=45.0;
win.scrollbar[1].xs=256.0;
win.scrollbar[1].ys=16.0;
win.scrollbar[1].fxs=8.0;
win.scrollbar[1].fys=19.0;
win.scrollbar[1].name="_vcl_scrollbar1";
win.scrollbar[1].hint="";
win.scrollbar[1].min=0.000;
win.scrollbar[1].max=1.000;
win.scrollbar[1].pos=0.000;
win.scrollbar[1].dpos=0.100;
win.scrollbar[1].horizontal=1;
win.scrollbar[1].style=0;
win.scrollbar[1].resize();
win.scrollbar[2].x0=200.0;
win.scrollbar[2].y0=70.0;
win.scrollbar[2].xs=256.0;
win.scrollbar[2].ys=16.0;
win.scrollbar[2].fxs=8.0;
win.scrollbar[2].fys=19.0;
win.scrollbar[2].name="_vcl_scrollbar2";
win.scrollbar[2].hint="";
win.scrollbar[2].min=0.000;
win.scrollbar[2].max=1.000;
win.scrollbar[2].pos=0.000;
win.scrollbar[2].dpos=0.100;
win.scrollbar[2].horizontal=1;
win.scrollbar[2].style=0;
win.scrollbar[2].resize();
win.interpbox.allocate(0);
win.interpbox.num=0;
win.dblist.allocate(0);
win.dblist.num=0;
// OpenGL VCL window end: win
//---------------------------------------------------------------------------
Look at images here plotting real time Data on Oscillocope for some ideas (I got this working for both GDI and OpenGL)
It is better to use pixel units instead of OpenGL <-1,+1> screen units for better visual quality and editing comfort.
I'm working on a tool that generates a grid of hexagons that the user can click on to cycle through certain states (Enemy, ally etc). So far, I've been able to generate the hexes as Polygons.
I'm fairly new to Windows programming and the Win32 API. I know how to create a regular button, but what would be the best way to deal with what I need?
The options that come to mind are:
Make the hex's pseudo-buttons. As in store the states of the hex objects and just draw the text on each hex as the user clicks on them.
Make actual hexagon shaped buttons using CreateWindow. I've found some examples of how to create different shaped buttons, but haven't tried myself.
Create image files to cycle through.
What is the correct way to go to do this? By correct I mean best practice.
If you are already drawing the hexagons (it sounds like you are) then making hexagon shaped buttons doesn't really do much for you. You can do the hit testing yourself to determine which pseudo-button was clicked. This avoids having Windows manage many small objects that you already have complete data about. And drawing the text on these buttons will be at least as fast as needing Windows to do it.
I'm making my own UI from scratch using OpenGL that is why I'm asking this and please don't make any discouragement as this is just a hobby project.
Currently, I'm stuck implementing how this scrollbars really work. In my current implementation, the content scrolls at the wrong step value as well as the thumb, meaning, I set the value manually like 1px step for each of them.
The structure of my scrollbar implementation is describe as follows:
I draw scrollbars i.e the main rectangle where the 3 button lies.
Those 3 buttons are, thumb, buttonBack and buttonNext.
All of them do the basic logic of scrollbars i.e when I click each one of them, they moved. But the whole part(scrollbar) don't know how to scroll contents
So what I did is: I make another object and I call it scrollarea
It has two scrollbars, vertical and horizontal scrollbar.
I made a function called scrollToX and scrollToY which
does what I named to them.
But the step values I set to them are
manually set up.
I try to google some scrollbar, scrollarea, scrollview or whatever you call to that scrollable rectangle thing, but all I see are implementation and I cannot find any guides how to build your own. I have no choice but to look at their implementation. I try my best to comprehend what they did but their implementation of how their whole UI structure is very different to mine, and I cannot find anything useful there.
So I ask again here if anybody can explain me well how to make a properly functional scrollbar.
Most specific things I'm really concerned of are:
How do I determine the thumb step value?
How do I determine the content step value?
All of these depend on your content -
Is it just an image ? If so, you only need to change the offset depending on the size of the image.
Is it a list of values like in Windows explorer ? Then you need to create a data structure first that contains all of it, and shows the content that fits within the window as it scrolls.
OpenGL does not fit into this discussion.
I have to design a GUI using Qt. I would like to draw multiple lines depicting relationships between two objects. It's the same idea as matching a word with a definition by drawing a straight line (which might be a diagonal) between the two.
In my case it is an a label (with image inside of it) that needs to be matched with another label.
So we have something like this - http://dl.dropbox.com/u/46437808/DrawLines.png
And I want to add lines to make it look something like this http://dl.dropbox.com/u/46437808/DrawLines2.png
I need to do this in run time because the relationship will be changing based on different factors.
Thanks!
Do you need interaction or is this just an image that the user needs to see based on other information? If it's just a static image, I would simply draw it onto a QImage and show it. That way you have complete control over how things are drawn. So you can either cache the relationship diagrams you need ahead of time, or just draw them on the fly onto the QImage based on the relationship that needs to be displayed at the time. You can look at Qt's painting example for some ideas on how to accomplish what you need.
If you need interactivity, I would probably go with the Graphics View Framework. This way if you need push buttons, check boxes, etc. for any reason you can use the QGraphicsProxyWidget to get them, or you can just make your own from QGraphicsItem subclasses.