📄 kslider.cpp
字号:
/* This file is part of the KDE libraries Copyright (C) 1997-1999 Christian Esken (esken@kde.org) (C) 1997 Martin Jones (mjones@kde.org) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*///-----------------------------------------------------------------------------// KSlider control V2.2// KSlider now maintained by Christian Esken (esken@kde.org)// Revision information.// 1.0 KSlider by Martin R. Jones// 1.1 All changes now by Christian Esken: sanity checks ( checkWidth() ).// 1.2 Implemented rangeChange()// 1.3 Reworked drawArrow(). For avoiding paint problems with some servers, I// am now painting the arrow with "precise" lines.// 2.0 Now KSlider is a derivation of QSlider// 2.1 Cleanups. Replacing eraseRect() by fillRect(). I would have thought,// eraseRect() would use BackgroundColor, but it doesn't.// 2.2 Cleaning up and inline documentantiaon. Correcting drawing of// vertical slider.#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <qpainter.h>#include <qdrawutil.h>#include "kslider.h"#include "kslider.h"#define ARROW_LENGTH 13KSlider::KSlider( QWidget *parent, const char *name ) : QSlider( parent, name ){ QSlider::setTickmarks(Below); isFocussed = false; update();}KSlider::KSlider( Orientation o, QWidget *parent, const char *name ) : QSlider( o, parent, name ){ QSlider::setTickmarks(Below); isFocussed = false; update();}KSlider::KSlider( int _minValue, int _maxValue, int _Step, int _value, Orientation o, QWidget *parent, const char *name ) : QSlider( _minValue, _maxValue, _Step, _value, o, parent, name ){ // We always have TickMarks if ( orientation() == QSlider::Vertical) { QSlider::setTickmarks(Right); } else QSlider::setTickmarks(Below); isFocussed = false; update();}void KSlider::drawShadeLine( QPainter *painter ){ if ( orientation() == QSlider::Vertical ) qDrawShadeLine(painter, 5, 3, 5, height()-3, colorGroup(), true, 1, 2); else qDrawShadeLine(painter, 3, 5, width()-3, 5, colorGroup(), true, 1, 2);}void KSlider::drawFocusBar(QPainter *painter, const QRect & ){/* if ( isFocussed ) painter->setPen(colorGroup().dark() ); else painter->setPen(colorGroup().background() );*/ if ( isFocussed ) qDrawPlainRect(painter,0,0,width(),height(), colorGroup().dark(),1,0); else qDrawPlainRect(painter,0,0,width(),height(), colorGroup().background(),1,0);}void KSlider::paintSlider(QPainter *painter, const QRect &re ){ QPoint pos; // erase old arrow pos = calcArrowPos( prevValue() ); drawArrow( painter, false, pos ); // show, if focussed drawFocusBar(painter, re); drawShadeLine(painter); // draw new arrow pos = calcArrowPos( value() ); drawArrow( painter, true, pos );}void KSlider::drawArrow( QPainter *painter, bool show, const QPoint &pos ){ QPen arrowPen; QPointArray array(5); // Select Horizontal or Vertical Polygon Array if ( orientation() == QSlider::Vertical ) { array.setPoint( 0, pos.x()+0, pos.y()+0 ); array.setPoint( 1, pos.x()-4, pos.y()+4 ); array.setPoint( 2, pos.x()-ARROW_LENGTH, pos.y()+4 ); array.setPoint( 3, pos.x()-ARROW_LENGTH, pos.y()-4 ); array.setPoint( 4, pos.x()-4, pos.y()-4 ); } else { array.setPoint( 0, pos.x()+0, pos.y()+0 ); array.setPoint( 1, pos.x()+4, pos.y()-4 ); array.setPoint( 2, pos.x()+4, pos.y()-ARROW_LENGTH ); array.setPoint( 3, pos.x()-4, pos.y()-ARROW_LENGTH ); array.setPoint( 4, pos.x()-4, pos.y()-4 ); } // Select a base pen, then change parameters if ( show ) arrowPen = QPen( colorGroup().light() ); else arrowPen = QPen( colorGroup().background() ); arrowPen.setWidth(1); // Yup, we REALLY want width 1, not 0 here !! painter->setPen(arrowPen); painter->setBrush( colorGroup().background() ); painter->drawPolygon( array ); if ( show ) { arrowPen = QPen( colorGroup().dark() ); arrowPen.setWidth(1); // Yup, we REALLY want width 1, not 0, here !! painter->setPen(arrowPen); painter->drawPolyline( array, 0, 3); // !!! This fixes a problem with a missing point! Qt Bug? // !!! I will wait for Qt1.3 to see the results // painter->drawPoint(array[1]); }}QSize KSlider::sizeHint() const{ QSize size; if ( orientation() == QSlider::Vertical ) { size.setWidth( ARROW_LENGTH + 5 + 1 ); size.setHeight( -1 ); } else { size.setWidth( -1 ); size.setHeight( ARROW_LENGTH + 5 + 1 ); } return size;}QPoint KSlider::calcArrowPos( int val ){ QPoint p; int diffMaxMin = checkWidth(); // sanity check, Christian Esken int noOffsetValue = val - minValue(); /** Calculate the arrow position. More precisely, calculate the position of the arrow "tip". Calculation works like this (in vertical case): x position is simply the arrow length. y position is more complicated: 1. There is always a 5 pixel border left and right This leaves "height()-10" point as working area 2. The slider range must be mapped linear onto the working area. a) So I calculate a relative Position in the slider range: (val - minValue() ) / (maxValue() - minValue() Actually I call it "noOffsetValue / diffmaxMin". b) I don't set the braces around "noOffsetValue / diffmaxMin" because this would loose precision. c) This will lead to a arrow position inside [ 0,height()-10 ] I do currect this, by "adding" 5. Actually I do reverse the slider, so that low values are at the bottom. This means, do not add "5", but "height()-5". */ if ( orientation() == QSlider::Vertical ) { p.setY( height() - 5 - ( ((height()-10) * noOffsetValue ) / diffMaxMin ) ); p.setX( ARROW_LENGTH ); } else { p.setX( 5 + ( ((width()-10) * noOffsetValue ) / diffMaxMin ) ); p.setY( ARROW_LENGTH ); } return p;}void KSlider::drawTickMarks(QPainter *painter){ QPen tickPen = QPen( colorGroup().dark() ); tickPen.setWidth(1); // Yup, we REALLY want width 1, not 0 here !! painter->setPen(tickPen); int i; int diffMaxMin = checkWidth(); // sanity check if ( orientation() == QSlider::Vertical ) { // first clear the tickmark area painter->fillRect(ARROW_LENGTH+1,0, ARROW_LENGTH + 6, height()-1, colorGroup().background() ); // draw ruler marks for ( i = 0; i <= maxValue() - minValue(); i += lineStep() ) { int pos = (height()-10) * i / diffMaxMin + 5; painter->drawLine( ARROW_LENGTH+1, pos, ARROW_LENGTH + 4, pos ); } for ( i = 0; i <= maxValue() - minValue(); i += pageStep() ) { int pos = (height()-10) * i / diffMaxMin + 5; painter->drawLine( ARROW_LENGTH+1, pos, ARROW_LENGTH + 6, pos ); } } else { // first clear the tickmark area painter->fillRect(0, ARROW_LENGTH+1, width()-1, ARROW_LENGTH + 6, colorGroup().background() ); // draw ruler marks for ( i = 0; i <= maxValue() - minValue(); i += lineStep() ) { int pos = (width()-10) * i / diffMaxMin + 5; painter->drawLine( pos, ARROW_LENGTH+1, pos, ARROW_LENGTH + 4 ); } for ( i = 0; i <= maxValue() - minValue(); i += pageStep() ) { int pos = (width()-10) * i / diffMaxMin + 5; painter->drawLine( pos, ARROW_LENGTH+1, pos, ARROW_LENGTH + 6 ); } }}void KSlider::drawTicks ( QPainter * p, int , int , int ){ drawTickMarks(p);}void KSlider::drawWinGroove (QPainter *, QCOORD){ // Do nothing}void KSlider::paintEvent( QPaintEvent *qpe ){ QPainter painter; painter.begin( this ); // build a rect for the paint event QRect rect(x(),y(),width(),height()); // Clear widget area, because there might be "pixel dirt" around. // Especially then, when rangeChange(), resizes, such things happen. painter.fillRect(qpe->rect().x(),qpe->rect().y(),qpe->rect().width(),qpe->rect().height(), colorGroup().background() ); // painter.eraseRect(qpe->rect().x(),qpe->rect().y(),qpe->rect().width(),qpe->rect().height()); paintSlider(&painter, rect); if ( orientation() == QSlider::Vertical ) { QRect TickRect(ARROW_LENGTH+1,0,width(),height()); if (qpe->rect().intersects(TickRect)) drawTickMarks(&painter); } else { QRect TickRect(0, ARROW_LENGTH+1,width(),height()); if (qpe->rect().intersects(TickRect)) { drawTickMarks(&painter); } } painter.end();}void KSlider::valueChange(){ QSlider::valueChange(); if ( orientation() == QSlider::Vertical ) repaint(0,0,ARROW_LENGTH,height()); else repaint(0,0,width(),ARROW_LENGTH);// emit valueChanged( value() );}void KSlider::rangeChange(){ QSlider::rangeChange(); // when range changes, everything must be repainted update();}int KSlider::checkWidth(){ int diff = maxValue() - minValue(); if ( diff == 0) // If (max - min) has no "secure" value, set it to lineStep(). diff=lineStep(); return diff;}void KSlider::paletteChange(const QPalette &){ update();}void KSlider::backgroundColorChange(const QPalette &){ update();}void KSlider::focusInEvent( QFocusEvent * ){ QPainter painter; QRect rect(x(),y(),width(),height()); painter.begin( this ); isFocussed = true; paintSlider(&painter,rect); painter.end();}void KSlider::focusOutEvent( QFocusEvent * ){ QPainter painter; QRect rect(x(),y(),width(),height()); painter.begin( this ); isFocussed = false; paintSlider(&painter,rect); painter.end();}#include "kslider.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -