In my application I need to switch frequently between two main screens (tripleplay.game.Screen)
In order to toggle between the two screens, I always keep one Screen on the tripleplay.game.ScreenStack and I push/remove the second Screen to/from ScreenStack.
This cause a lot of calls to wasAdded()/wasRemoved() methods of the second screen.
To avoid performance degradation I choosen to do nothing in the wasRemoved() method and I put an alreadyCreated flag on the MyScreen class to avoid execution of the logic contained in the wasAdded() method.
Is it possible to switch between two screens already on the ScreenStack without removing the topmost screen but simply swapping positions of the screens inside the stack?
Thanks in advance, Gio
Related
I'm still a beginner at Qt (5.15.2) and I'm trying to implement a way to setMaximumWidth of the application MainWindow based on the current screen it's on.
For example: if the application is on screen 1 (1366x768) it should have maximumWidth of 1366, if it goes to screen 2 (1920x1080), then it should have maximumWidth of 1920, and the same logic applies to a N number of screens. Is there a signal that can help me with this? If there is not, is there a good way to simulate a screen change signal?
What I tried:
I've searched for a QScreen::screenChanged signal but I couldn't find one, so I assume it doesn't exist.
I've tried using QGuiApplication::primaryScreenChanged(), but it didn't work because it only works with primary screens, so when I merely change screens the signal doesn't get activated, only if I go to windows and change the primary screen to the one I'm currently on (which is not desirable).
I've also thought of using timeout signal that would activate a function that checks the current screen and sets the maximum width, it probably would work, but it doesn't seem like a good solution performance wise.
Edit: as for what would cause the screen change, it would be the user, either by dragging the window to another screen or using shortcut keys.
Imagine a huge rectangular grid filled with tiles. The individual tiles are not very complicated, they are svg images containing a low amount of shapes.
The number of different types of tiles in not very large, I estimate in the low hundreds. However, the grid can become very large, so the number of total tiles is huge (at least tens of thousands, maybe more).
I have to be able to smoothly scroll the grid both horizontally and vertically, as well as smoothly zoom it in and out. I also have to be able to jump to a specific position.
It would also be nice if I could populate it asynchronously, first the elements which are actually visible, and then the rest. This means that a table-handling class where I first have to add rows and columns in a loop would not be the best solution, because the starting position is not necessarily the upper left corner.
Zooming is simply achieved by having all the width and height properties of the items within a tile specified as a multiple of a scaling factor. The svg shouldn't be a problem as the number of different images is not high, it should be able to be cached. In the unlikely case svg became the bottleneck, I could just use sets of different pngs in different resolutions.
I tried (or considered) the following approaches:
Using the methods of the SameGame example, creating QML objects dynamically (Component.createObject). This works if the number of objects is small, but is very slow with a large number of objects. Even if the objects are completely empty, this method takes a very long time.
Using a Repeater inside a Flickable. The Flickable contains a Grid, which is populated by a Repater. The Grid, of course, is immense.
This method is faster than creating the objects dynamically, but still inefficient as the number of tiles grows. The QML engine keeps track of every item, even those which are not visible. Zooming is also quite slow, as the properties of every item are recalculated, not just the visible ones.
Using a GridView. This looks like the perfect solution at a first glance. The GridView inherits Flickable, and it also takes care to only render contents which are within the bounds of the view. Even a test case with millions of svg images runs reasonably fast, and it scrolls and resizes smoothly. There is only one problem: The GridView is only flickable either horizontally or vertically, but not both. There has been a feature request about this since 2012, but it still seems to be ignored.
Using a QGraphicsView directly. It is capable of displaying, scrolling and zooming the needed amount of elements, but it's not QML-based. The rest of my GUI is in QML, and I've only read horror stories about combining QML and QGraphicsView. I've never seen any reasonable examples of it.
What other solutions are there? Some horrible hack of using Javascript to add and remove rows and columns of a simple GridLayout (which is only a couple rows and columns larger than the visible area) while it is moved around in a Flickable? Or just embedding an OpenGL window and drawing everything manually?
I hope this shouldn't be an impossible task. There were strategy games written more than 20 years ago for DOS and Windows 95 which could handle this amount of tiles, while additionally having textures and animations.
Yeah, Qt is very good at ignoring community suggestions for years, even if they would be extremely useful, considered important, and happen to be the most up-voted, such as zip support.
I personally wouldn't bother "fixing" GridView, but rather implement something from scratch that suits my specific requirements, in C++ so that it is fast and efficient. And it will be very easy if your tiles are uniform squares, and it sounds like you could get away with that, even if the actual images inside are not square. This will make it very easy to determined their positions programmatically, and also determine the top left corner tile, how much tiles per line and the stride for the subsequent lines. Then as the visibility rectangle moves you iterate your container and signal to create QML elements for those which enter visibility. Easy peasy.
You don't need anything fancy, just inherit QObject, register the type to QML, then go and populate it's internal "model". You definitely do not want to have all the objects in memory, even if the scene graph is smart enough to not render them, it will still be processing them, I suspect your drop in FPS is not the product of a GPU but a CPU bottleneck.
The actual grid object can emit creation and destruction signals with their data Q_SIGNAL void create(x, y, imgPath);, so you bind custom handlers on the QML side, which will give you flexibility and ease of use, such as easily specifying the "delegate" object, it will be more elegant than doing the actual creation/destruction in C++. You can use bindings on the QML side for the few items that are visible to track when they go out of screen to self-destruct, that would minimize complexity, as you won't have to track all the "living" objects.
Component {
id: objComponent
Image {
property bool isVisible: { is in grid.visibleRect ??? }
onIsVisibleChanged: if (!isVisible) destroy()
}
}
MyGrid {
id: grid
contentX: flickable.contentX
contentY: flickable.contentY
onCreate: objComponent.createObject(flickable.contentItem, {"x" : x, "y" : y, "source" : imgPath})
}
Flickable {
id: flickable
contentWidth: grid.contentWidth
contentHeight: grid.contentHeight
}
Normally, when a user has a question, important enough to offer a bounty I'd produce working code, but unfortunately I am currently too busy. The concept is pretty simple though and should not be too problematic to implement.
I am developing a UI container to hold UI components that can be dragged and dropped on to the container and also move components around within the container. The components are of various sizes. I'm doing this in flex/actionscript but I guess this problem applies to any user interface. Are there any resources (books, etc) that have layout algorithms. Any pointers on this will be a great help.
The user can drag/drop items. But the items should rearrange themselves so that there is no overlap. E.g. if a there are two items right next to each other and the user drops a third item on top of them (in the middle) the first two items should move aside to make room for the third item. (Similar to examples.adobe.com/flex3/devnet/dashboard/main.html except the item size vary).
The source code for the dashboard layout works with the assumptions all the components are the same dimensions. What I'm looking for is a way to layout components of different sizes.
Thanks
We've done some work like this in the past for a customer. What you need is an implementation of collision detection algorithm. See this http://code.google.com/p/collisiondetectionkit/
Also here is an article on code project that has some layout utilities in C# that implements this which you could probably port : http://www.codeproject.com/Articles/23871/WPF-Diagram-Designer-Part-3. Also
I have a Direct3D11 scene set up in SlimDX in a window. The rendering is done in a separate thread.
Is there a way to keep the renderer from stretching the image when it draws to the resized control? I've tried ModeDescription.Scaling = DisplayModeScaling.Centered and it doesn't seem to have any effect. Is there something I'm missing?
(I already am updating the render target size. The reason I ask this is that when I resize the control it stretches the image to fill the control for a split second before the render target gets updated with the new size. This has the result that as I resize it, it flickers terribly. If I could reset the render target just slightly faster it might get rid the the flicker. Keeping the image in the corner without scaling it is perfectly fine since ultimately it won't be scaling at all.)
Workaround 1: One can put the render target inside a control. When the window resizes only resize the control though a special method that first stops the rendering, then update the buffers and begins rendering again. It's a bit of hack, though. I have to wait for the render cycle to complete, then block it, then resize, then unblock.
Workaround 2: A similar workaround is to check for a resize flag in the render loop rather than interrupting it. The renderer should be able to draw directly without scaling. This is much more acceptable performancewise. However, a blocking call to the UI thread must be made to execute the actual resize.
Workaround 3: Rather than resizing the control at all, one could make it as large as the maximum size it could be, but clipped (inside the window). No resize is necessary, but a scissor rectangle must be maintained in a similar manner to the workarounds above unless you don't mind rendering a whole lot of offscreen pixels. Rendering twenty or so extra rows and columns of pixels does have the favorable effect of supplying immediate image at the edge when the window is resized back larger.
Ideally the resize should be done directly from the UI thread (no fooling around with delaying it and reentering the UI thread from the render thread). It's not the render thread's responsibility and it slows it down. Likewise, the buffer resize should be done in the render thread for maximum performance (no fooling around with waiting/blocking/resizing/unblocking). The only reason this does not work is that the render thread scales if the resize is done before the buffers are resized.
So my question still stands: Is there a way to render without scaling?
I am going to answer this in terms of the raw Win32 APIs involved, which might require a bit of finesse to translate to a managed .NET environment & SlimDX.
When you are dragging or resizing a window, windows basically hijacks your message pump and creates a new one specifically designed to do the resizing logic efficiently. This operation is more or less modal until it is completed. Many messages you would normally get are quite literally blocked until the resize or drag is completed. In the app terms you get a WM_ENTERSIZEMOVE when this behavior begins, and either WM_EXITSIZEMOVE or WM_CAPTURECHANGED when it ends. You need to check both of these messages, as alt-tabing out when doing a drag will send WM_CAPTURECHANGED and never a WM_EXITSIZEMOVE!
All this means that when you get a WM_ENTERSIZEMOVE you can set a flag and know that all WM_SIZE and WM_MOVE messages that occur afterwards are for the drag operation. Typically resizing rendertargets and tracking down and de-allocating all default pool resources is a very slow operation, and well worth defering until the drag/resize has completed. This has the side effect of making the window stretch which is exactly the same problem you are describing here, and you want to fix that.
It should be possible to add special handlers in WM_SIZE, WM_MOVE, or WM_SIZING, and WM_MOVING that forces a syncronous render and repaint via SendMessage (as opposed to PostMessage) when they occur, but you will need to make sure you only do this when inside the modal loop owned by WM_ENTERSIZEMOVE.
I would recommend either forcing the window to a fixed size (which seems rather common) or not redrawing the D3D control until the changes are done (that or simply clear it black).
There seems to be a way to do what you want, as I have seen games capable of changing size with no flicker, but I've no idea how that's done, unfortunately. Locking the window size and providing a menu was the old solution.
I am developing a flash based website using mxml. My monitor's resolution is 1280x768 and is widescreen. The problem is while it appears properly in my screen it doesn't appear properly in others. Which is the best approach to solve the problem ?
I have 2 in mind.
Let scrollbars take care of it : If the screen is 14 inch screen with
800x600 resolution it appears zoomed
in. So thats a problem
Get screen resolution and resize using scaleX and scaleY : The graphic
components will get resized but fonts
give problem.
Which is the best approach among these ? If there is a better approach please mention.
Thanks
The BEST approach for this is to create a fluent UI based on percentage and constraints.
This way, the UI will feel the same on all computers not just yours.
I would recommend to also use the flow container that comes as a part of flexLib because that way is the easiest to create a fluent design.
Not long ago I created an application for a forex company that was perfectly fit to all screens larger then 1280X800 (design definition).
It's not that hard to do once you get the hang of it.
Good luck.
You can add an event listener to the stage to this effect:
this.stage.addEventListener(Event.RESIZE, resizeHandler);
private function resizeHandler(e:Event):void {
var newWidth:Number = this.stage.stageWidth;
var newHeight:Number = this.stage.stageHeight;
// etc, roll from here to do your manual positioning logic.
}
Note that this should also work on any DisplayObject - so you can use constraints and percentages on your containers, but then intercept their auto-resizing with a setup like this which will let you fine-tune the appearance of their contents.
Personally I would develop the screen for 800x600 and then dynamically resize the screen for higher resolutions.
You can use vertical scrollbars but horizontal scrolling is a big no-no in my books. It takes away from the whole experience of your site and gets rather irritating.