返回介绍

Transformed Graphics Demo

发布于 2019-10-04 15:05:11 字数 14315 浏览 1005 评论 0 收藏 0

This example lets the user rotate, shear and scale text and graphics arbitrarily.


Implementation:

/****************************************************************************
** $Id:  qt/xform.cpp   3.0.5   edited Oct 12 2001 $
**
** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
**
** This file is part of an example program for Qt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#include <qapplication.h>

#include <qdialog.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qradiobutton.h>
#include <qbuttongroup.h>
#include <qlcdnumber.h>
#include <qslider.h>
#include <qmenubar.h>
#include <qfontdialog.h>
#include <qlayout.h>
#include <qvbox.h>
#include <qwidgetstack.h>

#include <qpainter.h>
#include <qpixmap.h>
#include <qpicture.h>

#include <stdlib.h>


class ModeNames {
public:
    enum Mode { Text, Image, Picture };
};


class XFormControl : public QVBox, public ModeNames
{
    Q_OBJECT
public:
    XFormControl( const QFont &initialFont, QWidget *parent=0, const char *name=0 );
   ~XFormControl() {}

    QWMatrix matrix();

signals:
    void newMatrix( QWMatrix );
    void newText( const QString& );
    void newFont( const QFont & );
    void newMode( int );
private slots:
    void newMtx();
    void newTxt(const QString&);
    void selectFont();
    void fontSelected( const QFont & );
    void changeMode(int);
    void timerEvent(QTimerEvent*);
private:
    Mode mode;
    QSlider      *rotS;                // Rotation angle scroll bar
    QSlider      *shearS;              // Shear value scroll bar
    QSlider      *magS;                // Magnification value scroll bar
    QLCDNumber   *rotLCD;              // Rotation angle LCD display
    QLCDNumber   *shearLCD;            // Shear value LCD display
    QLCDNumber   *magLCD;              // Magnification value LCD display
    QCheckBox    *mirror;              // Checkbox for mirror image on/of
    QWidgetStack* optionals;
    QLineEdit    *textEd;              // Inp[ut field for xForm text
    QPushButton  *fpb;                 // Select font push button
    QRadioButton *rb_txt;              // Radio button for text
    QRadioButton *rb_img;              // Radio button for image
    QRadioButton *rb_pic;              // Radio button for picture
    QFont currentFont;
};

/*
  ShowXForm displays a text or a pixmap (QPixmap) using a coordinate
  transformation matrix (QWMatrix)
*/

class ShowXForm : public QWidget, public ModeNames
{
    Q_OBJECT
public:
    ShowXForm( const QFont &f, QWidget *parent=0, const char *name=0 );
   ~ShowXForm() {}
    void showIt();                      // (Re)displays text or pixmap

    Mode mode() const { return m; }
public slots:
    void setText( const QString& );
    void setMatrix( QWMatrix );
    void setFont( const QFont &f );
    void setPixmap( QPixmap );
    void setPicture( const QPicture& );
    void setMode( int );
private:
    QSizePolicy sizePolicy() const;
    QSize sizeHint() const;
    void paintEvent( QPaintEvent * );
    void resizeEvent( QResizeEvent * );
    QWMatrix  mtx;                      // coordinate transform matrix
    QString   text;                     // text to be displayed
    QPixmap   pix;                      // pixmap to be displayed
    QPicture  picture;                  // text to be displayed
    QRect     eraseRect;                // covers last displayed text/pixmap
    Mode      m;
};

XFormControl::XFormControl( const QFont &initialFont,
                            QWidget *parent, const char *name )
        : QVBox( parent, name )
{
    setSpacing(6);
    setMargin(6);
    currentFont = initialFont;
    mode = Image;

    rotLCD      = new QLCDNumber( 4, this, "rotateLCD" );
    rotS        = new QSlider( QSlider::Horizontal, this,
                                  "rotateSlider" );
    shearLCD    = new QLCDNumber( 5,this, "shearLCD" );
    shearS      = new QSlider( QSlider::Horizontal, this,
                                  "shearSlider" );
    mirror      = new QCheckBox( this, "mirrorCheckBox" );
    rb_txt = new QRadioButton( this, "text" );
    rb_img = new QRadioButton( this, "image" );
    rb_pic = new QRadioButton( this, "picture" );
    optionals = new QWidgetStack(this);
    QVBox* optionals_text = new QVBox(optionals);
    optionals_text->setSpacing(6);
    QVBox* optionals_other = new QVBox(optionals);
    optionals_other->setSpacing(6);
    optionals->addWidget(optionals_text,0);
    optionals->addWidget(optionals_other,1);
    fpb         = new QPushButton( optionals_text, "text" );
    textEd      = new QLineEdit( optionals_text, "text" );
    textEd->setFocus();

    rotLCD->display( "  0'" );

    rotS->setRange( -180, 180 );
    rotS->setValue( 0 );
    connect( rotS, SIGNAL(valueChanged(int)), SLOT(newMtx()) );

    shearLCD->display( "0.00" );

    shearS->setRange( -25, 25 );
    shearS->setValue( 0 );
    connect( shearS, SIGNAL(valueChanged(int)), SLOT(newMtx()) );

    mirror->setText( tr("Mirror") );
    connect( mirror, SIGNAL(clicked()), SLOT(newMtx()) );

    QButtonGroup *bg = new QButtonGroup(this);
    bg->hide();
    bg->insert(rb_txt,0);
    bg->insert(rb_img,1);
    bg->insert(rb_pic,2);
    rb_txt->setText( tr("Text") );
    rb_img->setText( tr("Image") );
    rb_img->setChecked(TRUE);
    rb_pic->setText( tr("Picture") );
    connect( bg, SIGNAL(clicked(int)), SLOT(changeMode(int)) );

    fpb->setText( tr("Select font...") );
    connect( fpb, SIGNAL(clicked()), SLOT(selectFont()) );

    textEd->setText( "Troll" );
    connect( textEd, SIGNAL(textChanged(const QString&)),
                     SLOT(newTxt(const QString&)) );

    magLCD = new QLCDNumber( 4,optionals_other, "magLCD" );
    magLCD->display( "100" );
    magS = new QSlider( QSlider::Horizontal, optionals_other,
                           "magnifySlider" );
    magS->setRange( 0, 800 );
    connect( magS, SIGNAL(valueChanged(int)), SLOT(newMtx()) );
    magS->setValue( 0 );
    connect( magS, SIGNAL(valueChanged(int)), magLCD, SLOT(display(int)));

    optionals_text->adjustSize();
    optionals_other->adjustSize();
    changeMode(Image);

    startTimer(20); // start an initial animation
}

void XFormControl::timerEvent(QTimerEvent*)
{
    int v = magS->value();
    v = (v+2)+v/10;
    if ( v >= 200 ) {
        v = 200;
        killTimers();
    }
    magS->setValue(v);
}



/*
    Called whenever the user has changed one of the matrix parameters
    (i.e. rotate, shear or magnification)
*/
void XFormControl::newMtx()
{
    emit newMatrix( matrix() );
}

void XFormControl::newTxt(const QString& s)
{
    emit newText(s);
    changeMode(Text);
}

/*
    Calculates the matrix appropriate for the current controls,
    and updates the displays.
*/
QWMatrix XFormControl::matrix()
{
    QWMatrix m;
    if (mode != Text) {
        double magVal = 1.0*magS->value()/100;
        m.scale( magVal, magVal );
    }
    double shearVal = 1.0*shearS->value()/25;
    m.shear( shearVal, shearVal );
    m.rotate( rotS->value() );
    if ( mirror->isChecked() ) {
        m.scale( 1, -1 );
        m.rotate( 180 );
    }

    QString tmp;
    tmp.sprintf( "%1.2f", shearVal  );
    if ( shearVal >= 0 )
        tmp.insert( 0, " " );
    shearLCD->display( tmp );

    int rot = rotS->value();
    if ( rot < 0 )
        rot = rot + 360;
    tmp.sprintf( "%3i'", rot );
    rotLCD->display( tmp );
    return m;
}


void XFormControl::selectFont()
{
    bool ok;
    QFont f = QFontDialog::getFont( &ok, currentFont );
    if ( ok ) {
        currentFont = f;
        fontSelected( f );
    }
}

void XFormControl::fontSelected( const QFont &font )
{
    emit newFont( font );
    changeMode(Text);
}

/*
    Sets the mode - Text, Image, or Picture.
*/

void XFormControl::changeMode(int m)
{
    mode = (Mode)m;

    emit newMode( m );
    newMtx();
    if ( mode == Text ) {
        optionals->raiseWidget(0);
        rb_txt->setChecked(TRUE);
    } else {
        optionals->raiseWidget(1);
        if ( mode == Image )
            rb_img->setChecked(TRUE);
        else
            rb_pic->setChecked(TRUE);
    }
    qApp->flushX();
}

ShowXForm::ShowXForm( const QFont &initialFont,
                      QWidget *parent, const char *name )
        : QWidget( parent, name, WResizeNoErase )
{
    setFont( initialFont );
    setBackgroundColor( white );
    m = Text;
    eraseRect = QRect( 0, 0, 0, 0 );
}

QSizePolicy ShowXForm::sizePolicy() const
{
    return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
}

QSize ShowXForm::sizeHint() const
{
    return QSize(400,400);
}

void ShowXForm::paintEvent( QPaintEvent * )
{
    showIt();
}

void ShowXForm::resizeEvent( QResizeEvent * )
{
    eraseRect = QRect( width()/2, height()/2, 0, 0 );
    repaint(rect());
}

void ShowXForm::setText( const QString& s )
{
    text = s;
    showIt();
}

void ShowXForm::setMatrix( QWMatrix w )
{
    mtx = w;
    showIt();
}

void ShowXForm::setFont( const QFont &f )
{
    m = Text;
    QWidget::setFont( f );
}

void ShowXForm::setPixmap( QPixmap pm )
{
    pix  = pm;
    m    = Image;
    showIt();
}

void ShowXForm::setPicture( const QPicture& p )
{
    picture = p;
    m = Picture;
    showIt();
}

void ShowXForm::setMode( int mode )
{
    m = (Mode)mode;
}

void ShowXForm::showIt()
{
    QPainter p;
    QRect r;      // rectangle covering new text/pixmap in virtual coordinates
    QWMatrix um;  // copy user specified transform
    int textYPos = 0; // distance from boundingRect y pos to baseline
    int textXPos = 0; // distance from boundingRect x pos to text start
    QRect br;
    QFontMetrics fm( fontMetrics() );   // get widget font metrics
    switch ( mode() ) {
      case Text:
        br = fm.boundingRect( text );   // rectangle covering text
        r  = br;
        textYPos = -r.y();
        textXPos = -r.x();
        br.moveTopLeft( QPoint( -br.width()/2, -br.height()/2 ) );
        break;
      case Image:
        r = pix.rect();
        break;
      case Picture:
        // ### need QPicture::boundingRect()
        r = QRect(0,0,1000,1000);
        break;
    }
    r.moveTopLeft( QPoint(-r.width()/2, -r.height()/2) );
          // compute union of new and old rect
          // the resulting rectangle will cover what is already displayed
          // and have room for the new text/pixmap
    eraseRect = eraseRect.unite( mtx.map(r) );
    eraseRect.moveBy( -1, -1 ); // add border for matrix round off
    eraseRect.setSize( QSize( eraseRect.width() + 2,eraseRect.height() + 2 ) );
    int pw = QMIN(eraseRect.width(),width());
    int ph = QMIN(eraseRect.height(),height());
    QPixmap pm( pw, ph );               // off-screen drawing pixmap
    pm.fill( backgroundColor() );

    p.begin( &pm );
    um.translate( pw/2, ph/2 ); // 0,0 is center
    um = mtx * um;
    p.setWorldMatrix( um );
    switch ( mode() ) {
      case Text:
        p.setFont( font() );            // use widget font
        p.drawText( r.left() + textXPos, r.top() + textYPos, text );
#if 0
        p.setPen( red );
        p.drawRect( br );
#endif
        break;
      case Image:
        p.drawPixmap( -pix.width()/2, -pix.height()/2, pix );
        //QPixmap rotated = pix.xForm(mtx);
        //bitBlt( &pm, pm.width()/2 - rotated.width()/2,
                //pm.height()/2 - rotated.height()/2, &rotated );
        break;
      case Picture:
        // ### need QPicture::boundingRect()
        p.scale(0.25,0.25);
        p.translate(-230,-180);
        p.drawPicture( picture );
    }
    p.end();

    int xpos = width()/2  - pw/2;
    int ypos = height()/2 - ph/2;
    bitBlt( this, xpos, ypos,                   // copy pixmap to widget
            &pm, 0, 0, -1, -1 );
    eraseRect =  mtx.map( r );
}


/*
    Grand unifying widget, putting ShowXForm and XFormControl
    together.
*/

class XFormCenter : public QHBox, public ModeNames
{
    Q_OBJECT
public:
    XFormCenter( QWidget *parent=0, const char *name=0 );
public slots:
    void setFont( const QFont &f ) { sx->setFont( f ); }
    void newMode( int );
private:
    ShowXForm   *sx;
    XFormControl *xc;
};

void XFormCenter::newMode( int m )
{
    static bool first_i = TRUE;
    static bool first_p = TRUE;

    if ( sx->mode() == m )
        return;
    if ( m == Image && first_i ) {
        first_i = FALSE;
        QPixmap pm;
        if ( pm.load( "image.any" ) )
            sx->setPixmap( pm );
        return;
    }
    if ( m == Picture && first_p ) {
        first_p = FALSE;
        QPicture p;
        if (p.load( "picture.any" ))
            sx->setPicture( p );
        return;
    }
    sx->setMode(m);
}

XFormCenter::XFormCenter( QWidget *parent, const char *name )
    : QHBox( parent, name )
{
    QFont f( "Charter", 36, QFont::Bold );

    xc = new XFormControl( f, this );
    sx = new ShowXForm( f, this );
    setStretchFactor(sx,1);
    xc->setFrameStyle( QFrame::Panel | QFrame::Raised );
    xc->setLineWidth( 2 );
    connect( xc, SIGNAL(newText(const QString&)), sx,
                 SLOT(setText(const QString&)) );
    connect( xc, SIGNAL(newMatrix(QWMatrix)),
             sx, SLOT(setMatrix(QWMatrix)) );
    connect( xc, SIGNAL(newFont(const QFont&)), sx,
                 SLOT(setFont(const QFont&)) );
    connect( xc, SIGNAL(newMode(int)), SLOT(newMode(int)) );
    sx->setText( "Troll" );
    newMode( Image );
    sx->setMatrix(xc->matrix());
}


int main( int argc, char **argv )
{
    QApplication a( argc, argv );

    XFormCenter *xfc = new XFormCenter;

    a.setMainWidget( xfc );
    xfc->setCaption("Qt Example - XForm");
    xfc->show();
    return a.exec();
}

#include "xform.moc"                  // include metadata generated by the moc

See also Examples.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文