Project

General

Profile

Resizing a WPaintedWidget

Added by Stas Magill over 10 years ago

Hi,

I am using a WPaintedWidget to draw a graph and I need the widget to expand and shrink horizontally to fill the width within the browser window. My code worked with Wt 3.2.0, but has stopped working with the latest Wt 3.2.1. The graph expands ok when the browser is made wider, but it does not shrink when the browser is made narrower. The WPaintedWidget is inside a WContainerWidget (with a WHBoxLayout) which itself is inside a WPanel. I've attached a screen shot.

The code that creates the graph widget is:

    // Set up the graph
    m_graphWidget= new StatusGraphWidget();

    // Graph container and layout
    WContainerWidget* conGraph= new WContainerWidget();
    WHBoxLayout* layoutGraph= new WHBoxLayout();
    conGraph->setLayout(layoutGraph, AlignTop | AlignJustify);
    layoutGraph->setContentsMargins(0, 0, 0, 0);
    layoutGraph->addWidget(m_graphWidget, AlignTop | AlignJustify);

    m_panelGraph= new WPanel(this);
    m_panelGraph->setCentralWidget(conGraph);
    m_panelGraph->setTitle("Status graph");
    m_panelGraph->setCollapsible(true);

The StatusGraphWidget is of course derrived from a WPaintedWidget. The constructor just provides a default size and sets the "size-aware" flag:

    resize(16, 170);
    setLayoutSizeAware(true);

And the layoutSizeChanged handler does the following:

void StatusGraphWidget::layoutSizeChanged(int width, int height)
{
    resize(width, height);
    setLayoutSizeAware(true);
}

In the latest Wt release, this handler gets called when the browser is made wider, but not when it is made narrower (this is using Firefox 11). Does anyone have any idea what I need to do differently in the latest Wt release to get this working?

Thanks.


Replies (5)

RE: Resizing a WPaintedWidget - Added by Michael Leitman over 10 years ago

Hey Stas :)

I also have a few Problems with AutoResizing, SizeChanged handler and getting the height of widgets as is described here:

http://redmine.emweb.be/boards/2/topics/4044

You set the Alignment of the Layout and Container to AlignTop | AlignJustify

(look in the reference for more information on Alignment:

http://www.webtoolkit.eu/wt/doc/reference/html/classWt_1_1WContainerWidget.html#aff9884c8efdf90974077e96bcb1701db

void Wt::WContainerWidget::setLayout (WLayout *layout, WFlags< AlignmentFlag > alignment)

Sets a layout manager for the container.

The alignment argument determines how the layout is aligned inside the container. By default, the layout manager arranges children over the entire width and height of the container, corresponding to a value of AlignJustify. This requires that the container has a specified height (either because it is managed by another layout manager, is the root container widget, or has a height set).

In general, alignment is the logical OR of a horizontal and a vertical flag:

The horizontal alignment option may be one of Wt::AlignLeft, Wt::AlignCenter, Wt::AlignRight, or Wt::AlignJustify.
The vertical alignment option may be '0' (corresponding to vertical justification to the full height), or Wt::AlignTop.
When using a horizontal alingment different from Wt::AlignJustify, and a vertical alignment different from '0', the widget is sized in that direction to fit the contents, instead of the contents being adjusted to the widget size. This is useful when the container does not have a specific size in that direction and when the layout manager does not contain any widgets that wish to consume all remaining space in that direction.

Only a single layout manager may be set. If you want to replace the current layout manager, you have to erase all contents first using clear(), which also deletes the layout manager.

Note that you can nest layout managers inside each other, to create a complex layout hierarchy.

The widget will take ownership of layout.)

Maybe if you try setting no Alignment, so the content take all place? Or try and error with the AlignmentFlag?

hope you can get some help

  • the incredible Leitman

RE: Resizing a WPaintedWidget - Added by Stas Magill over 10 years ago

Thanks Michael, but I think I've tried every permutation of alignment flags that I could think of.

I have now reduced my graph widget to it's simplest form - just a horizontal box layout and the graph itself. In this set-up, the graph does not resize at all. The source code is below. Koen, Wim - I would much appreciate your thoughts on how to get this working.

Many thanks.

#include <Wt/WPaintedWidget>
#include <Wt/WPaintDevice>
#include <Wt/WPainter>
#include <Wt/WHBoxLayout>

#include <boost/thread.hpp>

#include "WtGraphApp.h"

using namespace std;
using namespace Wt;

class StatusGraphWidget : public Wt::WPaintedWidget
{
    public:
        StatusGraphWidget(void) :
            Wt::WPaintedWidget(),
            m_app(Wt::WApplication::instance()),
            m_threadRunning(false)
        {
            resize(16, 170);
            setLayoutSizeAware(true);

            m_app->enableUpdates(true);

            m_thread= boost::thread(boost::bind(&StatusGraphWidget::updateThread, this, 1000));
        }

        ~StatusGraphWidget()
        {
            m_threadRunning= false;
            m_thread.join();
        }

    private:

        Wt::WApplication* m_app;
        bool m_threadRunning;
        boost::thread m_thread;

        void updateThread(int frequency)
        {
            m_threadRunning= true;

            while (m_threadRunning)
            {
                Wt::WApplication::UpdateLock uiLock(m_app);
                if (uiLock)
                {
                    update(PaintUpdate);
                    m_app->triggerUpdate();
                }

                usleep(frequency * 1000);
            }
        }

        virtual void layoutSizeChanged(int width, int height)
        {
            cout << "SIZE CHANGED " << width << " " << height << endl;
            resize(width, height);
            setLayoutSizeAware(true);
        }

        virtual void paintEvent(Wt::WPaintDevice *paintDevice)
        {
            WPainter painter(paintDevice);

            int widgetWidth= width().toPixels();
            int widgetHeight= height().toPixels();

            ((WBrush&)painter.brush()).setStyle(SolidPattern);
            ((WPen&)painter.pen()).setColor(WColor(0, 0, 0, 255));
            painter.drawRect(0, 0, widgetWidth, widgetHeight);

            painter.setPen(WColor(0, 255, 0, 255));
            ((WPen&)painter.pen()).setWidth(WLength(2, WLength::Pixel));
            painter.drawLine(0, 0, widgetWidth, widgetHeight);
        }
};

WtGraphApp::WtGraphApp(const WEnvironment& env) :
    WApplication(env)
{
    setTitle("WtTest");

    WHBoxLayout* layout= new WHBoxLayout();
    layout->addWidget(new StatusGraphWidget(), 1, AlignTop | AlignJustify);

    root()->setLayout(layout, AlignTop | AlignJustify);
}

RE: Resizing a WPaintedWidget - Added by Wim Dumon over 10 years ago

Like this?

#include <Wt/WPaintedWidget>
#include <Wt/WPaintDevice>
#include <Wt/WPainter>
#include <Wt/WHBoxLayout>
#include <Wt/WApplication>
#include <Wt/WContainerWidget>

#include <Windows.h>

#include <boost/thread.hpp>

//#include "WtGraphApp.h" 

using namespace std;
using namespace Wt;

class StatusGraphWidget : public Wt::WPaintedWidget
{
    public:
        StatusGraphWidget(void) :
            Wt::WPaintedWidget(),
            m_app(Wt::WApplication::instance()),
            m_threadRunning(false)
        {
            setLayoutSizeAware(true);

            m_app->enableUpdates(true);

            m_thread= boost::thread(boost::bind(&StatusGraphWidget::updateThread, this, 1000));
        }

        ~StatusGraphWidget()
        {
            m_threadRunning= false;
            m_thread.join();
        }

    private:

        Wt::WApplication* m_app;
        bool m_threadRunning;
        boost::thread m_thread;

        void updateThread(int frequency)
        {
            m_threadRunning= true;

            while (m_threadRunning)
            {
              {
                Wt::WApplication::UpdateLock uiLock(m_app);
                if (uiLock)
                {
                    update(PaintUpdate);
                    m_app->triggerUpdate();
                }
              }
                Sleep(frequency);
            }
        }

        virtual void layoutSizeChanged(int width, int height)
        {
            cout << "SIZE CHANGED " << width << " " << height << endl;
            WPaintedWidget::layoutSizeChanged(width, height);
        }

        virtual void paintEvent(Wt::WPaintDevice *paintDevice)
        {
            WPainter painter(paintDevice);

            int widgetWidth= paintDevice->width().toPixels();
            int widgetHeight= paintDevice->height().toPixels();

            ((WBrush&)painter.brush()).setStyle(SolidPattern);
            ((WPen&)painter.pen()).setColor(WColor(0, 0, 0, 255));
            painter.drawRect(0, 0, widgetWidth, widgetHeight);

            painter.setPen(WColor(0, 255, 0, 255));
            ((WPen&)painter.pen()).setWidth(WLength(2, WLength::Pixel));
            painter.drawLine(0, 0, widgetWidth, widgetHeight);
        }
};

class WtGraphApp: public WApplication
{
public:
WtGraphApp(const WEnvironment& env) :
    WApplication(env)
{
    setTitle("WtTest");

    WContainerWidget *c = new WContainerWidget(root());
    WHBoxLayout* layout= new WHBoxLayout();
    layout->addWidget(new StatusGraphWidget(), 1, AlignJustify);

    c->setLayout(layout, AlignJustify);
    c->resize(WLength::Auto, 150);
}
};

WApplication *createApplication(const WEnvironment& env)
{
  /*
   * You could read information from the environment to de
   * the user has permission to start a new application
   */
  return new WtGraphApp(env);
}
int main(int argc, char **argv)
{
  return WRun(argc, argv, createApplication);
}

RE: Resizing a WPaintedWidget - Added by Stas Magill over 10 years ago

Thanks Wim. That works great!

RE: Resizing a WPaintedWidget - Added by Jonathan lisein about 3 years ago

Hi,

Because this is my first post, I want to thanks the whole team for their library.

I have implemented a custom MyPaintedWidget derived from Wt::WPaintedWidget and I would like to make this widget responsive to changes of device size ; in other word to resize it. I have tried to play with setLayoutSizeAware(1) and layoutSizeChanged(), as shown up by wim 7 years ago, but without success. I use WT layout, bootstrap template 3 responsive, wt 4.2.2 compiled from git source on ubuntu 18.

In the documentation, I haven't found any example of image/graph/painted widget with automatic resizing. Is there any? Can anybody provide a simple example of such things? I am almost sure it may help lot of newbies, including me.

regards,

Jo

    (1-5/5)