Quad Splitter Windows, an implementation?



  • How would I be able to implement a splitter window that looks like this?

    !http://img202.imageshack.us/img202/6717/hammer1y.jpg(Quad Splitter Window)!

    I tried to implement something like this (where both the horizontal and vertical bars are synchronized), but it doesn't work correctly:

    QuadSplit.h:
    @#ifndef QUADSPLIT_H
    #define QUADSPLIT_H

    #include <QApplication>
    #include <QSplitter>
    #include <QResizeEvent>

    class QuadSplit : public QSplitter
    {
    QSplitter parentSplit;
    QSplitter childSplit1;
    QSplitter childSplit2;

    QWidget *widget1;
    QWidget *widget2;
    QWidget *widget3;
    QWidget *widget4;
    
    void sync(QResizeEvent *resize)
    {
        moveSplitter(resize->size().width(),
                                 childSplit2.indexOf(widget4));
    }
    

    public:
    QuadSplit(QWidget *w1, QWidget *w2, QWidget *w3, QWidget *w4);
    void show() {parentSplit.show();}
    };

    #endif // QUADSPLIT_H
    @

    QuadSplit.cpp:
    @#include "QuadSplit.h"

    QuadSplit::QuadSplit(QWidget *w1, QWidget *w2, QWidget *w3, QWidget *w4)
    : widget1(w1),
    widget2(w2),
    widget3(w3),
    widget4(w4)
    {
    parentSplit.setOrientation(Qt::Vertical);

    childSplit1.addWidget(w1);
    childSplit1.addWidget(w2);
    childSplit2.addWidget(w3);
    childSplit2.addWidget(w4);
    
    parentSplit.addWidget(&childSplit1);
    parentSplit.addWidget(&childSplit2);
    
    connect (widget1,
             SIGNAL(resizeEvent(QResizeEvent *)),
             this,
             SLOT(sync(QResizeEvent *)));
    

    }
    @

    main.cpp:

    @#include <QApplication>
    #include <QTextEdit>
    #include "QuadSplit.h"

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QTextEdit *t1 = new QTextEdit;
    QTextEdit *t2 = new QTextEdit;
    QTextEdit *t3 = new QTextEdit;
    QTextEdit *t4 = new QTextEdit;
    
    QuadSplit quadSplit(t1, t2, t3, t4);
    quadSplit.show();
    
    return app.exec();
    

    }
    @

    Any suggestions?


  • Moderators

    I've done something similar with qscrollarea.

    Try connecting the valueChanged signal of one scrollbarslider with setvalue slot of the other and vice versa.



  • I'm not really working with scroll bars at the moment, more so the grab bars for the splitter windows. I still did something similar to what you said, and I finally got it.

    QuadSplit.h:

    @#ifndef QUADSPLIT_H
    #define QUADSPLIT_H

    #include <QSplitter>

    class QuadSplit : public QSplitter
    {
    Q_OBJECT

    QSplitter parentSplit;
    QSplitter childSplit1;
    QSplitter childSplit2;
    
    QWidget *widget1;
    QWidget *widget2;
    QWidget *widget3;
    QWidget *widget4;
    

    private slots:
    void sync1()
    {
    childSplit2.setSizes(childSplit1.sizes());
    }

    void sync2()
    {
        childSplit1.setSizes(childSplit2.sizes());
    }
    

    public:
    QuadSplit(QWidget *w1, QWidget *w2, QWidget *w3, QWidget *w4);
    void show() {parentSplit.show();}
    };

    #endif // QUADSPLIT_H
    @

    QuadSplit.cpp:

    @#include "QuadSplit.h"

    QuadSplit::QuadSplit(QWidget *w1, QWidget *w2, QWidget *w3, QWidget *w4)
    : widget1(w1),
    widget2(w2),
    widget3(w3),
    widget4(w4)
    {
    parentSplit.setOrientation(Qt::Vertical);

    childSplit1.addWidget(w1);
    childSplit1.addWidget(w2);
    childSplit2.addWidget(w3);
    childSplit2.addWidget(w4);
    
    parentSplit.addWidget(&childSplit1);
    parentSplit.addWidget(&childSplit2);
    
    connect (&childSplit1,
             SIGNAL(splitterMoved(int,int)),
             this,
             SLOT(sync1()));
    
    connect (&childSplit2,
             SIGNAL(splitterMoved(int,int)),
             this,
             SLOT(sync2()));
    

    }
    @

    main.cpp:

    @#include <QApplication>
    #include <QTextEdit>
    #include "QuadSplit.h"

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    QTextEdit *t1 = new QTextEdit;
    QTextEdit *t2 = new QTextEdit;
    QTextEdit *t3 = new QTextEdit;
    QTextEdit *t4 = new QTextEdit;
    
    QuadSplit quadSplit(t1, t2, t3, t4);
    quadSplit.show();
    
    return app.exec&#40;&#41;;
    

    }
    @

    I think the main things I screwed up on were:

    • Adding the Q_OBJECT macro and private slots keyword
    • Finding the right signal-specific member function in QSplitter
    • Using Build->qmake to run moc on the code, then building normally

    So... now it works. But is there any better way to implement this than what I currently have?


  • Moderators

    Glad it works now!

    My hint on the scrollbars was intended to give the four views kind of synchronizing on what to show. But as i see now you were more focussed on the sizes of te widgets.

    bq. So… now it works. But is there any better way to implement this than what I currently have?

    What do you mean by better? Faster, less resources? what is not working as expected?



  • For me, the structure of your QuadSplit looks a bit weird: you inherit QSplitter, and you also encapsulate three instances. Why do you do it like that? Will the inherited methods work as expected? I don't think so.

    So, perhaps you should make up your mind: is your QuadSplit a QSplitter? Can a user expect a QuadSplit to behave like a QSplitter if you pass a QuadSplit* where a QSplitter* is expected? If so, QuadSplit should inherit QSplitter.

    Or is the use of QSplitter simply an implementation detail? Then, you should use encapsulation. I think, this latter is much more likely. There are better ways of implementing your QuadSplit than using three QSplitters that need to be kept in sync. It should not matter much to the end-user of your class how the internals work.



  • Yeah, the reason why I'm asking for advice is for faster performance, cleaner syntax, etc.

    Andre, I suppose why I inherited from QSplitter is because, at first impression, I had intended it to be a splitter varient. But now that I think of it again it's really just an object of its own, and I agree that not all of the inherited functions will work anyway. Most would probably have to be reimplemented. For now I'll just inherit QuadSplit from QObject, I might narrow it down to its true "family line" if I want to venture into that, but I'm not sure if it's necessary. But maybe it is. After all I've barely looked through all of the member functions for these classes as of yet.

    bq. There are better ways of implementing your QuadSplit than using three QSplitters that need to be kept in sync.

    What do you have in mind? I could definatly use advice on how to improve it, whether performance or syntax wise.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.