2

OSXの「ドック」の機能に似たスライドする「サイドバー」を作りたいです(たとえば、マウスが画面の端を通過し、ドックがスライドします)。私はいじっていましたQDockWidgetが、それはウィンドウレイアウトに埋め込まれているため、表示されるとすべてがシフトします。

誰かがこれを実装する方法を提案できますか?

  • フローティングする必要はありません (別のウィンドウ/ツールバーとして)
  • ウィンドウの高さに合わせてスケーリングする必要があります (たとえば、ウィンドウはフルスクリーンまたはデフォルト サイズにすることができます)。
  • 複雑な場合は、スライド (アニメーション) する必要はありません。

私は Qt を初めて使用するので、これについて考えすぎたくありません。これはカスタム ウィジェットの問題ですか、それともボーダレス ウィンドウで表示する必要がありますか? カスタムウィジェットのアプローチは正しいようですが、他のウィンドウコンテンツをオーバーレイし、ウィンドウが拡大縮小する場合は拡大縮小するように指定する方法がわかりません。

4

1 に答える 1

2

QDockWidgetあなたが望むものとは何の関係もありません-行動的に。Dock ウィジェットと呼ばれているからといって、それが OS X と同じ "Dock" の概念であるという意味ではありません。単にどこかにドッキングするという意味です。QDockWidgetのドキュメントでは、ドッキング動作の意味を明確に説明しています。

以下のコードは、あなたが望むと思われる動作を実装しています。デザインが良いかどうかは議論の余地があります。コードが「複雑」な理由は、誰もそのような UI デザインを考え出すことが期待されていないことを暗示しているようです。実際にどこかのボタンをクリックしてスライダー ウィンドウを表示することの何が問題になっていますか?

コードは Qt 4.8 と 5.1 の両方で動作します。

注: これは Qt Quick 2 で実装されることを懇願します。それが目的で設計されたものです :) もちろん、Qt 4.6+ では QWidget を動かすアニメーションの動作が改善され、Qt 5 ではさらに微調整が行われていますが、実際にはこのコードは悪臭があり、 QWidget API は強力ですが、元の Macintosh がリリースされた 1984 年までさかのぼる一連の API を最終的にカプセル化します。積み上げられた多数のペインターからの結果を合成する必要がある場合、できることは限られています。Qt Quick では、レンダリングは GPU によって行われます。アニメーションは、2 つの新しい float を GPU に渡して単一の変換行列を更新することになります。それでおしまい。

#include <QApplication>
#include <QWidget>
#include <QGridLayout>
#include <QLabel>
#include <QPainter>
#include <QGradient>
#include <QMouseEvent>
#include <QPropertyAnimation>

class Slider : public QWidget {
    void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE {
        QPainter p(this);
        QLinearGradient g(QPointF(0,0), QPointF(rect().bottomRight()));
        g.setColorAt(0, Qt::blue);
        g.setColorAt(1, Qt::gray);
        p.setBackground(g);
        p.eraseRect(rect());
        p.setPen(Qt::yellow);
        p.setFont(QFont("Helvetica", 48));
        p.drawText(rect(), "Click Me To Hide");
    }
    void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE {
        hide();
    }
public:
    explicit Slider(QWidget *parent = 0) : QWidget(parent) {
        setAttribute(Qt::WA_OpaquePaintEvent);
    }
};

class Window : public QWidget {
    QGridLayout m_layout;
    Slider m_slider;
    QLabel m_label;
    QPropertyAnimation m_animation;
public:
    explicit Window(QWidget *parent = 0, Qt::WindowFlags f = 0) :
        QWidget(parent, f),
        m_layout(this),
        m_slider(this),
        m_animation(&m_slider, "pos")
   {
        setMouseTracking(true);
        m_layout.addWidget(&m_label);
        m_slider.hide();
        m_slider.setMouseTracking(false);
        m_animation.setStartValue(QPoint(-width(), 0));
        m_animation.setEndValue(QPoint(0, 0));
        m_animation.setDuration(500);
        m_animation.setEasingCurve(QEasingCurve::InCubic);
    }
    void leaveEvent(QEvent *) {
        if (window() && QCursor::pos().x() <= window()->geometry().topLeft().x()) {
            showSlider();
        }
    }
    void childEvent(QChildEvent * ev) {
        if (ev->added() && ev->child()->isWidgetType()) {
            ev->child()->installEventFilter(this);
            static_cast<QWidget*>(ev->child())->setMouseTracking(true);
        }
    }
    bool event(QEvent * ev) {
        eventFilter(this, ev);
        return QWidget::event(ev);
    }
    bool eventFilter(QObject *, QEvent * ev) {
        if (ev->type() == QEvent::MouseMove) {
            auto pos = QCursor::pos();
            if (window() && window()->isFullScreen()) {
                if (pos.x() <= window()->geometry().topLeft().x()) {
                    showSlider();
                }
            }
            m_label.setText(QString("%1, %2").arg(pos.x()).arg(pos.y()));
        }
        return false;
    }
    void resizeEvent(QResizeEvent *) {
        m_slider.resize(size());
        m_animation.setStartValue(QPoint(-width(), 0));
    }
    Q_SLOT void showSlider() {
        if (m_slider.isVisible() || (window() && qApp->activeWindow() != window())) return;
        m_slider.raise();
        m_slider.show();
        m_animation.start();
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Window w;
    w.show();
    return a.exec();
}
于 2013-09-02T13:41:09.053 に答える