How can i paint something larger on a QListWidgetItem? - c++

I intend to draw a long rectangle bar on a single QListWidgetItem and the code goes like:
QIcon icon(":/black.jpg");
ui->TimeLineDisplayer->addItem("");
ui->TimeLineDisplayer->item(0)->setIcon(icon);
ui->TimeLineDisplayer->setIconSize(QSize(500, 20));
where TimeLineDisplayer is a QListWidget.
The current problem is, there seems to be a limit to the width of the icon. So HOW can i draw a bar long enough on an item of a QListWidget?

my problem is solved by a rather primitive way:
QPixmap icon_pix = QPixmap(":/black.jpg");
ui->TimeLineDisplayer->addItem(0);
ui->TimeLineDisplayer->setIconSize(QSize(2000, 2000));
ui->TimeLineDisplayer->item(0)->setIcon(icon_pix.copy(QRect(0, 0, 500, 20)));
still not sure which sentence makes the real differnce, so do tell me about it if you have any idea.

Related

What might I be doing wrong to draw text with QPainter in QT 5 using C++?

In my paintEvent method for a custom widget for a game I'm writing, After calling the various model objects' render() methods to render them to the widget, I am trying to render the "Hi-Score" text. Here's the general code for just the text drawing:
painter.fillRect(event->rect(), QColor(0, 0, 0));
painter.drawImage(QRectF(event->rect().x(), event->rect().y() + 30, 512, 512), getGameBoardImage());
//...rendering other model components
painter.setBrush(QBrush(QColor(255, 255, 255)));
//painter.setFont(getGameFont());
painter.setFont(QFont("Times New Roman", 16, QFont::Bold));
painter.drawText(0, 0, "HI-SCORE");
I 'was' trying to draw the text in a custom font loaded from resource (I found an answer on here for that) but it wouldn't even display, even with a white brush. I thought maybe it was because it was because I didn't 'set' a font, but setting it to Times New Roman doesn't display anything either. What might I be doing wrong? As you can see the background is a black background with the game board painted on top but leaving a small buffer at the top and bottom. Do I need to do something special to display the text? Please don't suggest using a QLabel because I am trying to keep it all in one widget if possible. If I must, I will split the Hi-Score and 1-Ups into 2 other label sets with specialty fonts.
you code look ok, but you are drawing at 0,0 which is the top left corner of the widget canvas AND the text is actually there but not visible...
draw instead at
painter.drawText(margin, y+margin, "HI-SCORE");
where y is the high of the font used to draw the text and margin is you know a little margin border to make it look better something like 5 units
update
you can get the value of the text you are painting doing somthing like
QFont font("times", 25);
QFontMetrics fm(font);
int pixelsW{fm.width("HI-SCORE")};
int pixelsH{fm.height()};

How to resize pixmap in Qt?

I am trying to use a custom icon in a QtMessageBox, but can't resize the icon at all. The box shows up fine, but the icon is too large.
I've tried code from a similar question, but it didn't work.
QPixmap p(80,80);
p.scaled(80,80); //this doesn't seem to change anything
p.load("checkmark.png");
box->setIconPixmap(p);
How do I do this?
It is pointless to scale the pixmap before loading it, scale it afterwards.
QPixmap p("checkmark.png");
auto newPixmap = p.scaled(80, 80);
box->setIconPixmap(newPixmap);

Qt: How to create a scrollable, owner-drawn widget

I need to create a scrollable, owner-drawn widget that behaves a lot like QPlainTextEdit with word-wrapped text, in the sense that the height depends on the width - as the content width decreases, the content height increases.
What is the best approach to do it? I was thinking about putting my QWidget-derived class inside a QScrollArea, but QPlainTextEdit is derived from QScrollArea instead, should I go that route?
Also, I want to paint only the visible area in paintEvent(), it would be wasteful otherwise.
Right now I'm examining the code of QPlainTextEdit, but it is rather complex and not easy to read, so if anyone knows of a code example that's simpler on the web, you can give me a link, it would help a lot.
I'll post the solution I came up with. It's not the best, but it mostly works.
I did not derive from QAbstractScrollArea in the end, instead I simply embedded my widget in a QScrollArea with a vertical layout, which worked well-enough.
I implemented resizeEvent() (I saw this from QPlainTextEdit implementation), and each time the width changes, I recalculate the height, and I set the widget's minimum height to that. I set the minimum height because of how the layout works.
void MyWidget::resizeEvent(QResizeEvent *e)
{
// If the widget's width has changed, we recalculate the new height
// of our widget.
if (e->size().width() == e->oldSize().width()) {
return;
}
setMinimumHeight(calculateHeightFromWidth(e->size().width()));
}
For drawing only the visible area see Get visible area of QPainter

How to resize QWidget in a layout while aligning it to the center and maintaining aspect ratio

Ok, so I'd like to display an image with qt where the image resizes with the browser and maintains the aspect ratio while also remaining centered in the window. I can get the resizing with aspect ratio to work correctly, but when I align it with Qt::AlignCenter, the qwidget no longer resizes (remains a fixed size). So basically, I can get either option to work but not together.
A good example of what I'm trying to do would be the imshow() function in matlab. This resizes the image while maintaining the aspect ratio and also centering the image in the window. The code I have is soemthing like this:
void roilayout::resizeEvent(QResizeEvent *event)
{
QSize p(roiview->refimage->size());
p.scale(roiview->view->size(), Qt::KeepAspectRatio);
roiview->view->resize(p);
}
and in the constructor:
roiview = new roiwindow;
roiview->view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
roiview->view->setCursor(Qt::CrossCursor);
roiview->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
roiview->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QHBoxLayout *layoutContainer = new QHBoxLayout;
layoutContainer->addWidget(roiview->view);
setLayout(layoutContainer);
I searched google and couldnt find anything. Also asked a similar question a little while back but from the answers it appears I didn't ask the question clearly enough. Thanks.
A couple of things: First it would be helpful to know what type of control "view" is.
Also, I don't think you should need to resize the child control "view" (whatever type it is) within the parent's resizeEvent() callback.
A better solution might be to set the sizeHint policy on the child widget to automatically expand.

How to set an initial size of a QScrollArea?

I know that this is a very specific C++ and Qt related question, but maybe someone can help me, anyway ...
See the code below: I want to display an image within a scroll area. The view port of the scroll area shall have a defined initial size. That means, if the image's size is bigger than the initial size of the view port, scroll bars will be visible, otherwise not.
// create label for displaying an image
QImage image( ":/test.png" );
QLabel *label = new QLabel( this );
label->setPixmap( image.toPixmap() );
// put label into scroll area
QScollArea *area = new QScrollArea( this );
area->setWidget( label );
// set the initial size of the view port
// NOTE: This is what I'd like to do, but this method does not exist :(
area->setViewPortSize( QSize( 300, 300 ) );
It shall be possible to resize the whole application so that the view port will get another size than the initial one.
Unfortunatelly I was not able to find out, how to set the size of the view port. Qt's layout mechanism seems to set a default size for the view port, but up to now I was not able to change it. Setting a new size with
area->setMinimumSize( QSize( 300, 300 ) );
will actually set the demanded size, but then the scroll area looses the ability to get resized to a size smaller than 300x300.
Any ideas?
I think that you are looking at the problem the wrong way. The QScrollArea is just a widget that you put in a frame or QMainWindow. The size of the widget is controlled by the layout of the widget that contains it.
Take a look at this example from Trolltech: Image Viewer Example
You can try:
class MyScrollArea : public QScrollArea
{
virtual QSize sizeHint() const { return QSize( 300, 300 ); }
};
// create label for displaying an image
QImage image( ":/test.png" );
Label *label = new QLabel;
label->setPixmap( image.toPixmap() );
// put label into scroll area
QScollArea *area = new MyScrollArea( this );
area->setWidget( label );
However layout and Qt is amazingly Voodoo. It is IMO its least functional part.
if that doesn't work, try calling QWidget::resize() on various widgets.
Is the scroll area the top level widget? If so, simply call
area->resize(300,300);
If it's inside a hierarchy you need to resize the toplevel appropriately (complex), or set the minimumSize of the area. You could also try to experiment with the LayoutPolicy - assuming the sizeHint is QSize(300,300) you can give it the appropriate size policy according to what's defined in https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum
I don't think you can do exactly that very easily, which is (if I'm reading correctly), size the widget so that the internal area is 300x300. You might be able to fudge it, however, since a scroll area is a type of frame, which inherits from QWidget. This means you could just call area->resize( 300 + fudge, 300 + fudge ), where your fudge values account for the extra bit taken up by the frame's drawing.
I'm not sure this would work in a dynamically resizable dialog, however. I haven't ever done anything quite like this.
If you're trying to display an image inside a scroll area, your best bet isn't going with a label.
You should try using a QGraphicsView/QGraphicsScene/QGraphicPixmapItem (instead of the Scroll Area and label). The performance is far better when displaying images. The scroll area and label will re-draw the image very poorly as you move around using the scroll bars.
For example, you have a ".ui" file with a QGraphicsView on the gui called "qgvImageView" and a QImage called "image"...
QGraphicsScene *scene = new QGraphicsScene(qgvImageView);
QPixmap pixTmp(QPixmap::fromImage(image));
QGraphicsPixmapItem * ppixItem = scene->addPixmap( pixTmp );
ppixItem->setPos(0,0);
Check out the QT Documentation. BTW: This was introduced in Qt 4.2
I'm not sure if this will specifically fix the problem, but there is a chance that the QGraphicsView will react better to what you're trying to do.
How about using
area->setGeometry(int x, int y, int w, int h);