I have a simple to do tree application that displays a QTreeView inside of a QMainWindow. I want to give the user the ability to change the magnification level of the content (using a spinbox most likely), but without actually changing the underlying font size of the text.
Is there a way to do this without changing my whole app to a QGraphicsScene? The app is just showing a good-old fashioned tree with text, no graphics or anything fancy other than wanting to change the magnification of the view; hence, I am thinking that switching to a graphics scene would be overkill.
Or, am I wrong, and switching to a graphics scene is the only simple way to do it?
Note a trimmed down version of the app is at Code Review. It contains a SSCCE, but is a bit long to post here.
In a site discussing how to put widgets on a scene, trolltech wrote (emphasis added):
I myself and several other Trolls’ve spent some time researching this
topic [how to embed a widget in a QGraphicsScene]. It’s not trivial;
most solutions to embedding widgets into a scene end up with several
serious drawbacks. That’s also why Qt doesn’t have any off-the-shelf
solution to this.
Widgets cannot be scaled or rotated, but graphics items can.
This suggests I cannot perform, in a simple way, the operations I want to on my QWidget by itself. That is, perhaps I need to add it to a scene, which is what I was trying to avoid. If that is the answer, then I'll accept it and start a new question if I get stuck doing that.
Note I just found this question, which is pretty much a duplicate, and does not have an (accepted) answer.
Related content
http://www.qtcentre.org/threads/62745-Zoom-a-view
QTableView Zoom In/Out
Drawing widgets (such as buttons) over QGraphicsView
QGraphicsView Zooming in and out under mouse position using mouse wheel
https://forum.qt.io/topic/15308/qgraphicsview-zooming-with-qslider
https://wiki.qt.io/Smooth_Zoom_In_QGraphicsView
As suggested by the docs quoted from trolltech in the original question, there is no built-in method to zoom on a view.
If the goal is to avoid the use of QGraphicsViews, the simplest way to separate the size of the font on the screen, versus the size of the font saved or printed, is to basically have two fonts. One to be displayed on the screen you can call 'zoom', versus the other to be saved/printed and call that 'font size'.
I got this idea from qtcentre (in a post I added to the original post too):
http://www.qtcentre.org/threads/62745-Zoom-a-view
Related
I want to make an application that will benefit both from OpenGL and QML advantages. I want to use QOpenGLWidget and place QML Item over it. Item will be partially transparent. I though it may be possible by using QQuickView but I just figured out that it does cover all transparent parts with black color. An attempt to achieve what I need (an example project) may be found on my GitHub here.
Is it possible to render QML Item with all children onto an existing QWidget in such way that it is visible under Item, wherever Item is not completely opaque?
I guess that in the worst case scenario I could create bitmaps from the QWidget and the Item objects, somehow combine and display them but I seek easier way. If there is no easier way I could just never display those two at the same time.
The reason why I do not want to use OpenGL features in QML directly is this. Maybe I should just use the work around mentioned in the link.
I think you don't need Widgets for it. You can do custom rendering in QtQuick using QQuickFramebufferObject class. I used to do it before, though don't have code anymore. This article seems to explain what to do https://blog.qt.io/blog/2015/05/11/integrating-custom-opengl-rendering-with-qt-quick-via-qquickframebufferobject/
I'm comfortable with C++ but brand new to Qt. I apologize for my ignorance as I'm sure this is a very simple question. I'd like to make a custom clickable widget, basically a push button that is just a black square with Qt designer, but don't have any idea on where to start.
EDIT: after fumbling around I think I'm an epsilon closer.
I created a black_box.png file. In the resource browser I created a new resource and prefix, and added the black_box.png. Any advice from here?
You have a few options for what you want to achieve.
You can use custom painting to draw a new button that subclasses QPushButton, this is reasonably involved and provides a huge amount of flexibility to build it to your requirements.
You can use Qt's stylesheets mechanism to style it, you can get more information on it here: http://doc.qt.io/qt-5/stylesheet.html
Or you can set a QPixmap of your image to be a button icon, and size your button to match it, there's a good answer on how to do this on this question: How to set image on QPushButton?
I'm upgrading some Qt (C++ & QML) code from Qt4.8 to Qt5.1.
The Qt4.8 code is a trivial C++ "QML viewer" app subclassing a QDeclarativeView, and a bunch of QML.
It's been easy enough to change this to use Qt5/QtQuick2's QQuickView except for one thing:
The Qt4.8 app has a method for printing to PDF:
void MyQMLViewer::printToPDF(const QString& filename) const {
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setPageSize(QPrinter::A3);
printer.setOutputFileName(filename);
printer.setOrientation(QPrinter::Landscape);
QPainter painter(&printer);
render(&painter);
}
There were a few "environment" changes needed for Qt5.1 to get a QPrinter (ie add QT += printsupport to the project .pro file and #include <QtPrintSupport>), but there seems to be a more fundamental problem that QQuickView doesn't provide anything which is obviously compatible with the QGraphicsView/QPainter/QPaintDevice world of QPrinter (specifically, QQuickView has no render method, and all the drawing/painting/rendering-related methods it does have seem very tied up with OpenGL).
Any suggestions for how to best obtain high-quality PDF output from a QQuickView ?
(Note that I am not simply looking to screenshot the view; with QDeclarativeView, the code above generates PDFs with much better resolution even than the app fullscreened on my largest monitor).
I see the "QDeclarativeItem and QDeclarativeView" section of the "Porting QML Applications to Qt 5" guide does mention the loss of QGraphicsView-specific functionality, but doesn't offer any solutions (although it does mention workrounds for the case of items with custom QPainter-based rendering being bought into the new regime).
Update with some additional background info: an example of a PDF printed from QDeclarativeView using the above code can be found here. There's a png of the same view on a decent size monitor here. (This is actually the last slide in a series of slides; it's actually a gallery of the previous slides which bounces each slide onto the screen; if I had the time I'd look into the feasibility of the gallery being the only thing and transforming each scattered slide into view for a Prezi-style presentation; suspect QDeclarative isn't really performant enough though, which is one reason for wanting to get onto QtQuick2+Qt5.2's new scene graph stuff). Anyway, If you zoom the PDF up to 100% you'll see the text is... well it's better than anything a sanely sized image file will manage I think, although the sloping text baselines perhaps look a little uneven. There is also an issue with opacity values not being represented in the PDF (so the drop shadows and "bubbles" come out solid); another one of my motivations for trying for a QtQuick2 version was actually to see if translucent elements were dealt with any better. I assume the PDF just contains rasterized (or maybe vector outlines) of all the elements as utilities like "pdftotext" can't extract anything from it. I don't know enough about PDF tools to know how to inspect the internal structure of the thing but I assume there's some hierarchy there and the QML element tree is all laid out using a similar structure of nested transforms to the QML. Just for comparison and the sort of richness I'm potentially working towards here's a poster I did with LaTeX/Beamerposter; I find Beamerposter's rigid block structure rather limiting (and fiddly) compared with the possibilities QML seems to offer though. BTW, another thing on my wishlist/todolist is a QML element which can render LaTeX source, math and all, just to get the best of both worlds.
Update: Recent Qt blog post on all the backend changes in Qt5.8 has a comment linking to this Qt issue to use the new possibility of QPainter-rendered QtQuick scenes to render PDFs.
At the moment, there is no code in Qt that supports rendering of a scene graph to a pdf. The underlying data that is used to render Qt Quick 2 is held in the scene graph. As Laszlo suggests, you'd need to iterate the scene graph and generate PDF primitives. There's some impedance mismatch there, but it should be doable with some sweat. I think a proof of concept could be small enough to fit here, so I'll see how easy it could be :)
If you really want a PDF, you currently have no choice but to render it to a large image at 300dpi and wrap that in a PDF. The image doesn't have to be large if the poster has large areas of solid color. PDF can do do TIFF encoding and also JPEG encoding.
I'm going to start programming a 2D tile-based game in Qt and read about the QGraphicsScene and QGraphicsView classes which are intended for displaying and handling lots of 2D objects.
My question is that will it be feasible to create a world with lots of tiles using QGraphicsScene? Can I add the whole world at once tile-by-tile or should I try to implement something to restrict the area a bit? I've read that QGraphicsScene can handle "thousands of items" but a 2D tile map can easily get really, really big (200x200 tiles? not that many, but that's already 40,000 objects which is a lot).
The map is also going to be pretty much static so it might be possible to draw it as one big pixmap but this really prevents you from using all the fancy stuff in QGraphicsScene like handling mouse clicks on independent items etc. On top of that I'm going to draw the player, the NPCs and so forth which will not be aligned to the tile grid. Are there some optimization stuff for using lots of static objects and some dynamic ones on top of them?
Is using QGraphicsScene and QGraphicsView even a good idea at all or should I try to look for an alternative inside Qt or maybe a different, more game-oriented library?
Thanks in advance
You should use QGraphicsView.
The 40,000 Chips int the Qt Documentation is your best example to closely examine. It deals with the complexity of large numbers of elements, drawing them at multiple scales and a lot more.
Play with the example and you will see that all the chips actually make up a large photo if you zoom out and that you can select, and drag and drop multiple chips at any view, or you can zoom in enough to see some text on an individual chip. It will take time to understand each part, but this is a very thorough example to look into.
In the chips.cpp source, it shows how it can still run quickly by using a "LevelOfDetail" or lod variable switch statement based off of the transformation stored in a style option.
Qt Graphics View has been optimized to do a lot of the things you have talked about in your question, but it takes a while to understand how to approach it.
If you are still having issues with the size of the map you want to use, I would store tile layouts on the harddrive and load the ones you need when you need them, and remove the ones you don't need off of the scene as necessary.
QGraphicsScene has the ability to only paint what is being represented in the view, everything else just sits in the the scene index. You have different options for configuring how the scene and view operate to optimize your specific use. Just because you have 40k tiles in your scene index, doesn't mean you need to paint that many. You really only have as many as are being displayed in the resolution of your view.
Also, there are caching options if your items are static, then they only have to be calculated once and can be retrieved from a pixmap cache.
Ultimately I think its completely worth your time to try it out. It should be fairly easy for you to mock up a test where you populate your scene with a very large number of tiles and simply try scrolling around the view. I feel its not so much a concern with how many tiles you have, but rather how complex the graphics are within the actual view being painted.
I'm working on a similar project and I'm using a 30x30 grid of persistent QGraphicsPixmapItems. When the view of the map changes, the QGraphicsscene iterates over the part of the map array that's currently in view, calling setPixmap on each tile to change it over to the new tile type. It's been working pretty smoothly and I don't have any performance complaints thus far.
I agree with what has been said. I've been doing QGraphicsView-based games for years (if you're on Linux, ask your package manager for KDiamond or Palapeli if you like), and while rendering performance has been an issue when QGraphicsView first came out years ago, these problems are now generally solved.
What you should be concerned about is memory consumption. The chips example may have as many chips as you want to have tiles, but those chips are not kept in memory as pixmaps. If each tile is a fixed-size 50x50px image, that's already
32bits*50px*50px*200*200 = 381,9 MiB
Currently, I am in the design phase of a Qt widget like what one would see in a typical hex editor. It seemed simple enough to begin with, but as I dig into its implementation details I’m having some confusion.
Basically, the widget would consist of 3 core components: It will inherit QAbstractScrollArea or QScrollArea to provide scrolling and, in the viewport margin, it will display the file offset of each line. Then there will be two text editors; one with the hexadecimal value of each byte of the file, and one with the plaintext character representation.
I, of course, first checked qt-apps.org for any existing widgets, but a search for “hex” only returned QHexEdit and qPHexEditor, neither of which are very complete. I then considered creating a widget completely from scratch as they had, but felt like there should be a more elegant solution. Qt already has much text-editor functionality built into QTextEdit and QPlainTextEdit; why reinvent the wheel?
Now, while the “plaintext view” would be as simple as using a QPlainTextEdit with a fixed-width font and a width of 16 characters, the “hex view” is giving me a headache. I’ve been poring over QTextEdit, QAbstractTextDocumentLayout, etc., trying to figure out a way to present the desired appearance. For those who have never used a hex editor, it should function like so: – Using a fixed-width font, widget should be the width of 47 characters – Widget should display 2 hexadecimal characters per byte, with a blank space between bytes—-16 bytes per line
Since that thought, I’ve been trying to figure out how to subclass any related classes to provide the desired formatting. Unfortunately, the text editing classes don’t seem to follow the model/view framework as closely as I’d hoped, so deriving a new “view” for it doesn’t seem easy. Ideally, the widget would function like so:
One document/model for both the “hex” and “plaintext” views. Editing either view would adjust this model and update the other view appropriately. Signals/Slots at its best.
Because QTextEdit and QPlainTextEdit already provide much of the functionality needed (visible cursor, selections, undo/redo, native look and feel, etc), it would be ideal to re-use this.
So, does anyone have any recommendations? I appreciate any input on this.
QHexEdit2 is a quite complete editor widget for binary data. It can edit very big files, is available for Qt4, Qt5, PyQt4, PyQt4 with python 2 and 3.
see https://github.com/Simsys/qhexedit2