📄 q3scrollview.cpp
字号:
labels as child widgets. When the view is scrolled the viewport() is moved; its children move with it as child widgets normally do. \target allviews \section1 Details Relevant for All Views Normally you will use the first or third method if you want any child widgets in the view. Note that the widget you see in the scrolled area is the viewport() widget, not the Q3ScrollView itself. So to turn mouse tracking on, for example, use viewport()->setMouseTracking(true). To enable drag-and-drop, you would setAcceptDrops(true) on the Q3ScrollView (because drag-and-drop events propagate to the parent). But to work out the logical position in the view, you would need to map the drop co-ordinate from being relative to the Q3ScrollView to being relative to the contents; use the function viewportToContents() for this. To handle mouse events on the scrolling area, subclass scrollview as you would subclass other widgets, but rather than reimplementing mousePressEvent(), reimplement contentsMousePressEvent() instead. The contents specific event handlers provide translated events in the coordinate system of the scrollview. If you reimplement mousePressEvent(), you'll get called only when part of the Q3ScrollView is clicked: and the only such part is the "corner" (if you don't set a cornerWidget()) and the frame; everything else is covered up by the viewport, clipper or scroll bars. When you construct a Q3ScrollView, some of the window flags apply to the viewport() instead of being sent to the QWidget constructor for the Q3ScrollView. \list \i An image-manipulation widget would use \c WNoAutoErase|WStaticContents because the widget draws all pixels itself, and when its size increases, it only needs a paint event for the new part because the old part remains unchanged. \i A scrolling game widget in which the background scrolls as the characters move might use \c WNoAutoErase (in addition to \c WStaticContents) so that the window system background does not flash in and out during scrolling. \i A word processing widget might use \c WNoAutoErase and repaint itself line by line to get a less-flickery resizing. If the widget is in a mode in which no text justification can take place, it might use \c WStaticContents too, so that it would only get a repaint for the newly visible parts. \endlist Child widgets may be moved using addChild() or moveChild(). Use childX() and childY() to get the position of a child widget. A widget may be placed in the corner between the vertical and horizontal scroll bars with setCornerWidget(). You can get access to the scroll bars using horizontalScrollBar() and verticalScrollBar(), and to the viewport with viewport(). The scroll view can be scrolled using scrollBy(), ensureVisible(), setContentsPos() or center(). The visible area is given by visibleWidth() and visibleHeight(), and the contents area by contentsWidth() and contentsHeight(). The contents may be repainted using one of the repaintContents() or updateContents() functions. Coordinate conversion is provided by contentsToViewport() and viewportToContents(). The contentsMoving() signal is emitted just before the contents are moved to a new position. \warning Q3ScrollView currently does not erase the background when resized, i.e. you must always clear the background manually in scrollview subclasses. This will change in a future version of Qt and we recommend specifying the \c WNoAutoErase flag explicitly.*//*! \enum Q3ScrollView::ResizePolicy This enum type is used to control a Q3ScrollView's reaction to resize events. \value Default the Q3ScrollView selects one of the other settings automatically when it has to. In this version of Qt, Q3ScrollView changes to \c Manual if you resize the contents with resizeContents() and to \c AutoOne if a child is added. \value Manual the contents stays the size set by resizeContents(). \value AutoOne if there is only one child widget the contents stays the size of that widget. Otherwise the behavior is undefined. \value AutoOneFit if there is only one child widget the contents stays the size of that widget's sizeHint(). If the scrollview is resized larger than the child's sizeHint(), the child will be resized to fit. If there is more than one child, the behavior is undefined.*///#### The widget will be resized to its sizeHint() when a LayoutHint event//#### is received/*! Constructs a Q3ScrollView called \a name with parent \a parent and widget flags \a f. The widget flags \c WStaticContents, \c WNoAutoErase and \c WPaintClever are propagated to the viewport() widget. The other widget flags are propagated to the parent constructor as usual.*/Q3ScrollView::Q3ScrollView(QWidget *parent, const char *name, Qt::WindowFlags f) : Q3Frame(parent, name, f & (~WStaticContents) & (~WNoAutoErase) & (~WResizeNoErase)){ WindowFlags flags = WResizeNoErase | (f&WPaintClever) | (f&WRepaintNoErase) | (f&WStaticContents); d = new Q3ScrollViewData(this, flags);#ifndef QT_NO_DRAGANDDROP connect(&d->autoscroll_timer, SIGNAL(timeout()), this, SLOT(doDragAutoScroll()));#endif connect(d->hbar, SIGNAL(valueChanged(int)), this, SLOT(hslide(int))); connect(d->vbar, SIGNAL(valueChanged(int)), this, SLOT(vslide(int))); connect(d->hbar, SIGNAL(sliderPressed()), this, SLOT(hbarIsPressed())); connect(d->hbar, SIGNAL(sliderReleased()), this, SLOT(hbarIsReleased())); connect(d->vbar, SIGNAL(sliderPressed()), this, SLOT(vbarIsPressed())); connect(d->vbar, SIGNAL(sliderReleased()), this, SLOT(vbarIsReleased())); d->viewport->installEventFilter(this); connect(&d->scrollbar_timer, SIGNAL(timeout()), this, SLOT(updateScrollBars())); setFrameStyle(Q3Frame::StyledPanel | Q3Frame::Sunken); setLineWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth)); setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));}/*! Destroys the Q3ScrollView. Any children added with addChild() will be deleted.*/Q3ScrollView::~Q3ScrollView(){ // Be careful not to get all those useless events... if (d->clipped_viewport) d->clipped_viewport->removeEventFilter(this); else d->viewport->removeEventFilter(this); // order is important // ~QWidget may cause a WM_ERASEBKGND on Windows delete d->vbar; d->vbar = 0; delete d->hbar; d->hbar = 0; delete d->viewport; d->viewport = 0; delete d; d = 0;}/*! \fn void Q3ScrollView::horizontalSliderPressed() This signal is emitted whenever the user presses the horizontal slider.*//*! \fn void Q3ScrollView::horizontalSliderReleased() This signal is emitted whenever the user releases the horizontal slider.*//*! \fn void Q3ScrollView::verticalSliderPressed() This signal is emitted whenever the user presses the vertical slider.*//*! \fn void Q3ScrollView::verticalSliderReleased() This signal is emitted whenever the user releases the vertical slider.*/void Q3ScrollView::hbarIsPressed(){ d->hbarPressed = true; emit(horizontalSliderPressed());}void Q3ScrollView::hbarIsReleased(){ d->hbarPressed = false; emit(horizontalSliderReleased());}/*! Returns true if horizontal slider is pressed by user; otherwise returns false.*/bool Q3ScrollView::isHorizontalSliderPressed(){ return d->hbarPressed;}void Q3ScrollView::vbarIsPressed(){ d->vbarPressed = true; emit(verticalSliderPressed());}void Q3ScrollView::vbarIsReleased(){ d->vbarPressed = false; emit(verticalSliderReleased());}/*! Returns true if vertical slider is pressed by user; otherwise returns false.*/bool Q3ScrollView::isVerticalSliderPressed(){ return d->vbarPressed;}/*! \reimp*/void Q3ScrollView::styleChange(QStyle& old){ QWidget::styleChange(old); updateScrollBars(); d->cachedSizeHint = QSize();}/*! \reimp*/void Q3ScrollView::fontChange(const QFont &old){ QWidget::fontChange(old); updateScrollBars(); d->cachedSizeHint = QSize();}void Q3ScrollView::hslide(int pos){ if (!d->signal_choke) { moveContents(-pos, -d->contentsY()); QApplication::syncX(); }}void Q3ScrollView::vslide(int pos){ if (!d->signal_choke) { moveContents(-d->contentsX(), -pos); QApplication::syncX(); }}/*! Called when the horizontal scroll bar geometry changes. This is provided as a protected function so that subclasses can do interesting things such as providing extra buttons in some of the space normally used by the scroll bars. The default implementation simply gives all the space to \a hbar. The new geometry is given by \a x, \a y, \a w and \a h. \sa setVBarGeometry()*/void Q3ScrollView::setHBarGeometry(QScrollBar& hbar, int x, int y, int w, int h){ hbar.setGeometry(x, y, w, h);}/*! Called when the vertical scroll bar geometry changes. This is provided as a protected function so that subclasses can do interesting things such as providing extra buttons in some of the space normally used by the scroll bars. The default implementation simply gives all the space to \a vbar. The new geometry is given by \a x, \a y, \a w and \a h. \sa setHBarGeometry()*/void Q3ScrollView::setVBarGeometry(QScrollBar& vbar, int x, int y, int w, int h){ vbar.setGeometry(x, y, w, h);}/*! Returns the viewport size for size (\a x, \a y). The viewport size depends on (\a x, \a y) (the size of the contents), the size of this widget and the modes of the horizontal and vertical scroll bars. This function permits widgets that can trade vertical and horizontal space for each other to control scroll bar appearance better. For example, a word processor or web browser can control the width of the right margin accurately, whether or not there needs to be a vertical scroll bar.*/QSize Q3ScrollView::viewportSize(int x, int y) const{ int fw = frameWidth(); int lmarg = fw+d->l_marg; int rmarg = fw+d->r_marg; int tmarg = fw+d->t_marg; int bmarg = fw+d->b_marg; int w = width(); int h = height(); bool needh, needv; bool showh, showv; int hsbExt = horizontalScrollBar()->sizeHint().height(); int vsbExt = verticalScrollBar()->sizeHint().width(); if (d->policy != AutoOne || d->anyVisibleChildren()) { // Do we definitely need the scroll bar? needh = w-lmarg-rmarg < x; needv = h-tmarg-bmarg < y; // Do we intend to show the scroll bar? if (d->hMode == AlwaysOn) showh = true; else if (d->hMode == AlwaysOff) showh = false; else showh = needh; if (d->vMode == AlwaysOn) showv = true; else if (d->vMode == AlwaysOff) showv = false; else showv = needv; // Given other scroll bar will be shown, NOW do we need one? if (showh && h-vsbExt-tmarg-bmarg < y) { if (d->vMode == Auto) showv=true; } if (showv && w-hsbExt-lmarg-rmarg < x) { if (d->hMode == Auto) showh=true; } } else { // Scroll bars not needed, only show scroll bar that are always on. showh = d->hMode == AlwaysOn; showv = d->vMode == AlwaysOn; } return QSize(w-lmarg-rmarg - (showv ? vsbExt : 0), h-tmarg-bmarg - (showh ? hsbExt : 0));}/*! Updates scroll bars: all possibilities are considered. You should never need to call this in your code.*/void Q3ScrollView::updateScrollBars(){ if(!horizontalScrollBar() && !verticalScrollBar()) return; // I support this should use viewportSize()... but it needs // so many of the temporary variables from viewportSize. hm. int fw = frameWidth(); int lmarg = fw+d->l_marg; int rmarg = fw+d->r_marg; int tmarg = fw+d->t_marg; int bmarg = fw+d->b_marg; int w = width(); int h = height(); int portw, porth; bool needh; bool needv; bool showh; bool showv; bool showc = false; int hsbExt = horizontalScrollBar()->sizeHint().height(); int vsbExt = verticalScrollBar()->sizeHint().width(); QSize oldVisibleSize(visibleWidth(), visibleHeight()); if (d->policy != AutoOne || d->anyVisibleChildren()) { // Do we definitely need the scroll bar? needh = w-lmarg-rmarg < d->contentsWidth(); if (d->inresize) needh = !horizontalScrollBar()->isHidden(); needv = h-tmarg-bmarg < contentsHeight(); // Do we intend to show the scroll bar? if (d->hMode == AlwaysOn) showh = true; else if (d->hMode == AlwaysOff) showh = false; else showh = needh; if (d->vMode == AlwaysOn) showv = true; else if (d->vMode == AlwaysOff) showv = false; else showv = needv;#ifdef Q_WS_MAC bool mac_need_scroll = false; if(!parentWidget()) { mac_need_scroll = true; } else { QWidget *tlw = window(); QPoint tlw_br = QPoint(tlw->width(), tlw->height()), my_br = qt_mac_posInWindow(this) + QPoint(w, h); if(my_br.x() >= tlw_br.x() - 3 && my_br.y() >= tlw_br.y() - 3) mac_need_scroll = true; } if(mac_need_scroll) { WindowAttributes attr; GetWindowAttributes((WindowPtr)handle(), &attr); mac_need_scroll = (attr & kWindowResizableAttribute); } if(mac_need_scroll) { showc = true; if(d->vMode == Auto) showv = true; if(d->hMode == Auto) showh = true; }#endif // Given other scroll bar will be shown, NOW do we need one? if (showh && h-vsbExt-tmarg-bmarg < contentsHeight()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -