I have several QGraphicItems in a QGraphicsScene.
I want to modify only some of them when the QGraphicsView containing the scene gets resized.
The reason is that I have painted a grid respective to the view.
So how can I identify the items making up the grid in a QGraphivcsView::resizeEvent()?
Would it be possible to adjust the scene in a way that a given area (sceneRect) is always filling the complete view?
So how can I identify the items making up the grid in a QGraphivcsView::resizeEvent()?
One way would be to simply use dynamic_cast and QGrahpicsScene::items():
foreach( QGraphicsItem *item, myScene->items() )
{
GridItem *gridItem = dynamic_cast<GridItem*>( item );
if( gridItem )
{
// Apply appropriate transformation here
}
}
A slightly more "Qt" way to do the above would be to ensure your QGraphicsItem subclass reimplements QGraphicsItem::type()
foreach( QGraphicsItem *item, myScene->items() )
{
if( item->type() == GridItem::Type )
{
// Apply appropriate transformation here
}
}
Would it be possible to adjust the scene in a way that a given area
(sceneRect) is always filling the complete view?
QGraphicsView::fitInView() should do the trick
Also, while I'm not entirely sure what you're trying to accomplish, it sounds to me that you may want to check out the QGraphicsItem::ItemIgnoresTransformations flag.
myItem->setFlag( QGraphicsItem::ItemIgnoresTransformations )
which makes it so that any item with the given flag will not be affected by changes in the zoom level.
Related
I have applied resizeEvent to a QWidget. I am trying to resize the widget inside another widget. I have a QWT plot that should also resize.
I have applied resizeEvent to the QWidget and resized to the plot:
void SampleWidget:: resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
int diffofWidth = event->size().width() - event->oldSize().width();
int diffofHeight = event->size().height() - event->oldSize().height();
QSize size = plot->size();
if ((event->oldSize().width() >= 0) && (event->oldSize().height() >= 0))
{
if (event->size().width() <= this->minimumWidth() && event->size().height() <= this->minimumHeight())
{
return;
}
else
{
plot->resize(size.width() + diffofWidth, size.height() + diffofHeight);
plot->replot();
}
}
}
The widget is able to resize, but after resizing many times, the plot is only displayed partially in the widget. I am not able to see whole content in the widget. What's going on here?
Assuming you are asking why your widget isn't resizing properly, you likely have minimum sizes set within the layouts. Be sure that your minimum size of the parent is greater than or equal to the sum of it's children, that could cause the child elements to be partially hidden.
Also, check sizehint and the minimum size set for each object, increase them as needed.
I would like to write a custom QLabel subclass with some more features for responsive design. In thisexample, I want to write a QLabel which scales the text based on the useable space. This is quite easy but also has some problems because of Qt-intern stuff. (I have to scale the text to 0.9 of the useable space, otherwise resizing the window / widget gets buggy)
Now I wan't to add a way to hide the label completely when the font size is bellow a specific threshold. However, this seems to be quite a complex task.
Here is what I have sofar in the classes resizeEvent(QResizeEvent *event) function.
Right now, my function only sets the text to "" when the size would be bellow the threshold.
void CustomLabel::resizeEvent (QResizeEvent * event ) {
if(autoFontResize) {
this->setSilentText(labelText); // just the normal setText function, I overwrote it for the subclass
QFont f = this->font();
int flags = Qt::TextDontClip|Qt::TextWordWrap;
QRect fontBoundRect = this->fontMetrics().boundingRect(this->rect(), flags, this->text());
float xFactor = (float)event->size().width() / (float)fontBoundRect.width();
float yFactor = (float)event->size().height() / (float)fontBoundRect.height();
float factor = xFactor < yFactor ? xFactor : yFactor;
f.setPointSizeF(f.pointSize()*factor*0.9); //
if(minimumFontSize != 0) { // 0 = no minimum Size for the font
if(f.pointSize() < minimumFontSize) {
if(hideFontOnMinimum) { // either Hide or set to the limit size
this->setSilentText(""); //replace text
} else {
f.setPointSizeF(minimumFontSize);
}
}
}
this->setFont(f);
}
QLabel::resizeEvent(event);
}
By the way, some parts of the code are found on stackoverflow, not mine. ;)
What I would like to do is to completely hide() the label. However the label doesn't know when It can show() again since the resizeEvent doesn't seem to be called after that.
Any ideas?
Thanks!
As you've noticed, if you call hide() on the widget it fails to receive a resize event. Since you're customising the class anyway, rather than calling hide(), you could just set a class variable to note that it's hidden and overload the paintEvent function, not to draw the widget if the variable is set: -
void CustomLabel::paintEvent(QPaintEvent * event)
{
if(m_hideOnMinimum)
return;
QLabel::paintEvent(event);
}
Note that by not painting the label, it will be hidden, but the user may still be able to interact with it, so you will need to disable it or overload keyboard / mouse events too.
I have a panel.ui file done using QTDesigner. It's a QFrame class, rectangular shape with few labels on it. And I have a QListWidget class where I insert 3 instances of the panel.ui.
I create a QListWidgetItem and then use List->SetItemWidget(..) to populate my list.
The Result is a list filled with three panels. I was also able to move the panels inside the list using dragDropMode internalMove.
I also tested the ability to shift the panels a bit to the right when I click on them and that worked:
in procedure List::mousePressEvent(QMouseEvent *event)
Panel *child = static_cast<Panel*>(childAt(event->pos()))
...
int y= child->pos().y();
int x = child->pos().x();
child->move (x +10, y); `
Problem: When I run the app and display the list, I want all the panels to be displayed with that 10 offset to the right. So in the List constructor and inside the loop after this->setItemWidget(myPanelItem, myPanel); I try using myPanel->move() like above but it doesn't seem to work.
I run the app, the panels are displayed without my offset ( not sure why?) but when I click on one, it shifts.
move() won't work reliably since the widgets are in a layout. (Well, not a layout as in a QLayout, but the effect is comparable: When any metric in your application changes, e.g. you resize or scroll the list, the widgets are repositioned by the list widget.)
What you can do is wrap your actual widget in a container widget with a layout margin:
QWidget* wrapIntoContainerForOffset(QWidget* widget, int offset /*in pixels*/) {
QWidget* container = new QWidget;
QHBoxLayout* layout = new QLayout(container);
layout->setContentsMargins(/*left=*/ offset, /*others=*/ 0, 0, 0);
layout->addWidget(widget);
return container;
}
Then you add these containers to the listwidget instead.
Have You tried StyleSheets. The QListWidget supports Box model( http://doc.qt.digia.com/qt/stylesheet-customizing.html#box-model ). So You may want to try playing around with margins in the stylesheets.
Style sheet reference: http://doc.qt.digia.com/qt/stylesheet-reference.html
With some help from you QT sages, I was able to implement this window, with the desired layout and resizeability behavior. Now I have another interesting problem.
I want my entire window to have a "repeat-xy" seamless pattern. If I apply it to a simple window without layout and internal widgets, it works perfectly. I do however, now have a "tree" of widgets within widgets, and I can't set the stylesheet to draw my seamless background image to each and every one, cause it looks unnatural. The image must be underlying to all the widget topology I have. The problem is, it's invisible when i apply it to the bottom all-window-covering widget because it has widgets on top of it.
Is there a solution? maybe "transparent widgets" that can contain visible widgets?
I made the following using only CSS, there's a QPlainTextEdit, two QPushButton and a QLineEdit. In the image i added a red border to the QPlainTextEdit only so it can be seen, the rules are the following
QWidget#Form{
background-image: url(:/img/elephant_pattern.gif);
}
QPlainTextEdit{
background:transparent;
border:1px solid red;
}
As you can see all i had to was setting background transparent in the widgets i wanted.
Write your own widget that inherits QWidget. Reimplement the paintEvent and leave it empty. The widget itself won't be drawn, but its children will be.
my_widget::my_widget( QWidget* parent ) : QWidget( parent )
{
}
void my_widget::paintEvent( QPaintEvent* p_event )
{
// left empty to let my_widget be invisible
}
test_mw::test_mw( QWidget *parent ) : QMainWindow( parent )
{
test_widget = new my_widget( this );
QHBoxLayout* layout = new QHBoxLayout();
QPushButton* button0 = new QPushButton( "Button 0", 0 );
QPushButton* button1 = new QPushButton( "Button 1", 0 );
layout->addWidget( button0 );
layout->addWidget( widget );
test_widget->setLayout( layout );
setCentralWidget( test_widget );
}
Although the paintEvent of my_widget is empty, both QPushButtons are drawn. :-)
There was a QWidget::setBackgroundOrigin() method in earlier versions of Qt.
It's all done with styles now. See the examples http://doc.qt.nokia.com/latest/widgets-styles.html
Is there a built in way to determine if a component is fully visible in a Flex application (i.e. not offscreen one way or the other). If not how would I go about figurin it out?
I want to show or hide additional 'next' and 'previous' buttons if my primary 'next' and 'previous' buttons are off screen.
What event would be best to listen to to 'recalculate' ? stage.resize?
thanks!
here is a method for calculating if the component is within the bounds of the stage, it will not however tell you if the component is being hidden by another component, or if the component is being hidden because it is outside the bounds of another container.
public function isComponentWithinStage(c:UIComponent):Boolean {
var tl:Point = c.localToGlobal(new Point(0, 0));
var br:Point = c.localToGlobal(new Point(c.width, c.height));
//are we off the left or top of stage?
if ( tl.x < 0 || tl.y < 0 ) {
return false;
}
var stage:Stage = Application.application.stage;
//off the right or bottom of stage?
if ( br.x > stage.width || br.y > stage.height ) {
return false;
}
return true;
}
Could you give the specifics of the visible item and the container(s) it's in? Is it a matter of having to scroll some container to get to the buttons? Or is it a matter of someone has dragged a child window of a flexlib:MDICanvas partially off screen?
I think it's going to come down to if the x,y position of the component is beyond the width and height of its container, (and so on up through the parent containers until you reach your top level Application.)