There is a parent child relationship between two items. The child item which is a QGraphicsPixmapItem(image) was receiving all the events independently when rendered on the scene. But when I make a QGraphicsLineItem as its parent and rendered the image wrt parent item, I am unable to receive any event for the child. Please help, why is it happening?
My image item has events like hoverEnterEvent(), hoverLeaveEvent(), mouseMoveEvent() etc. Should all the events which are implemented in child item have a definition in parent too?
My parent does not have hoverEnterEvent() & hoverLeaveEvent(). I have also installed event filter on the child item. The parent item should receive all the events but it is not receiving any event at all. The important point to note is that I have rendered the image item wrt parent coordinate system. does it impact in any way. Please find the attached image.
Please find the child image item code below:
PersonSizeGraphicsItem::PersonSizeGraphicsItem(const QPixmap &pixmap, QGraphicsItem* parent_graphics_item, QGraphicsScene *scene)
:QGraphicsPixmapItem(pixmap, parent_graphics_item, scene),
parent_item(parent_graphics_item)
{
this->setParentItem(parent_item);
this->setFlag(QGraphicsItem::ItemIsMovable, true);
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setFocus(Qt::MouseFocusReason);
this->setAcceptHoverEvents(true);
//this->setScale(0.5);
rect_left_condition = false;
rect_right_condition = false;
rect_top_condition = false;
rect_bottom_condition = false;
rect_resize_occurred = false;
this->source_image = this->pixmap().toImage();
image_rect = QRect();
initializeImageRect();
}
PersonSizeGraphicsItem::~PersonSizeGraphicsItem()
{
}
int PersonSizeGraphicsItem::type() const
{
return item_type;
}
void PersonSizeGraphicsItem::initializeImageRect()
{
update();
}
void PersonSizeGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
const QPointF event_scene_pos = event->scenePos();
QPolygonF poly_rect = this->mapToParent(this->boundingRect());
qreal width = poly_rect.boundingRect().width();
qreal height = poly_rect.boundingRect().height();
// coordinates of item's bounding rect in scene coorinates.
QPointF _p1 = poly_rect.boundingRect().topLeft(); // (X,Y)
QPointF _p2 = poly_rect.boundingRect().topRight(); // (X + width,Y)
QPointF _p3 = poly_rect.boundingRect().bottomRight(); //(X+width, Y+height)
QPointF _p4 = poly_rect.boundingRect().bottomLeft(); //(X,Y+ height)
rect_left_condition = ( event_scene_pos.x() > ( _p1.x() - 5 ) && event_scene_pos.x() < ( _p1.x() + 5 ) );
rect_right_condition = ( event_scene_pos.x() > ( _p3.x() - 5 ) && event_scene_pos.x() < ( _p3.x() + 5 ) );
rect_top_condition = ( event_scene_pos.y() > ( _p1.y() - 5 ) && event_scene_pos.y() < ( _p1.y() + 5 ) );
rect_bottom_condition = ( event_scene_pos.y() > ( _p3.y() - 5 ) && event_scene_pos.y() < ( _p3.y() + 5 ) );
if( rect_left_condition || rect_right_condition )
{
this->setCursor(Qt::SizeHorCursor);
return;
}
if( rect_top_condition || rect_bottom_condition )
{
this->setCursor(Qt::SizeVerCursor);
return;
}
}
void PersonSizeGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
const QPointF event_scene_pos = event->scenePos();
QPolygonF poly_rect = this->mapToParent(this->boundingRect());
qreal width = poly_rect.boundingRect().width();
qreal height = poly_rect.boundingRect().height();
// coordinates of item's bounding rect in scene coorinates.
QPointF _p1 = poly_rect.boundingRect().topLeft(); // (X,Y)
QPointF _p2 = poly_rect.boundingRect().topRight(); // (X + width,Y)
QPointF _p3 = poly_rect.boundingRect().bottomRight(); //(X+width, Y+height)
QPointF _p4 = poly_rect.boundingRect().bottomLeft(); //(X,Y+ height)
bool horizontal_condition = (event_scene_pos.x() > ( _p1.x()+ 8)) && (event_scene_pos.x() < (_p3.x() -8) );
bool vertical_condition = (event_scene_pos.y() > ( _p1.y()+ 8)) && (event_scene_pos.y() < (_p3.y() -8) );
if( horizontal_condition && vertical_condition )
{
this->setCursor(Qt::SizeAllCursor);
}
}
void PersonSizeGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
this->setCursor(Qt::ArrowCursor);
rect_left_condition = false;
rect_right_condition = false;
rect_top_condition = false;
rect_bottom_condition = false;
QGraphicsItem::hoverLeaveEvent(event);
}
/*----------------------------------------------------------------------------------------------------*/
/* Purpose: method called when mouse is pressed on the graphics item */
/*--------------------------------------------------------------------------------------------------- */
void PersonSizeGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if( this->cursor().shape() == Qt::SizeAllCursor )
{
QMimeData * mimeData = new QMimeData;
PersonSizeGraphicsItem * item = this;
QByteArray byteArray(reinterpret_cast<char*>(&item),sizeof(PersonSizeGraphicsItem*));
mimeData->setData("Item",byteArray);
// start the event
QDrag * drag = new QDrag(event->widget());
drag->setMimeData(mimeData);
drag->exec();
// dragStart = event->pos();
event->accept();
}
}
void PersonSizeGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
const QPointF event_pos = event->pos();
const QPointF event_scene_pos = event->scenePos();
QPoint current_top_left = image_rect.topLeft();
QPoint current_bottom_right = image_rect.bottomRight();
if((event->scenePos().x() > this->scene()->width()) || (event->scenePos().y() > this->scene()->height())
|| (event->scenePos().x() < 0) || (event->scenePos().y() < 0) )
{
return;
}
if( this->cursor().shape() == Qt::SizeHorCursor )
{
if(rect_right_condition)
{
image_rect = QRect( current_top_left, QPoint( event->pos().x(), current_bottom_right.y()) );
if( image_rect.width() <=8 || image_rect.height() <=24 )
{
return;
}
rect_resize_occurred = true;
}
if(rect_left_condition)
{
//image_rect = QRect( QPoint(event_pos.x(), 0), current_bottom_right );
image_rect = QRect( QPoint(event_pos.x(), current_top_left.y()), current_bottom_right );
if( image_rect.width() <=8 || image_rect.height() <=24 )
{
return;
}
rect_resize_occurred = true;
}
}
if( this->cursor().shape() == Qt::SizeVerCursor )
{
if(rect_bottom_condition)
{
image_rect = QRect(current_top_left, QPoint(current_bottom_right.x(), event->pos().y()));
if( image_rect.width() <=8 || image_rect.height() <=24 )
{
return;
}
rect_resize_occurred = true;
}
if(rect_top_condition)
{
image_rect = QRect(QPoint(current_top_left.x(), event_pos.y()), current_bottom_right);
if( image_rect.width() <=8 || image_rect.height() <=24 )
{
return;
}
/* QPoint new_top_left = image_rect.topLeft();
QPointF mapped_topLeft = mapToParent(QPointF(new_top_left.x(),new_top_left.y()));
this->setPos(mapped_topLeft); */
rect_resize_occurred = true;
}
}
this->update();
}
void PersonSizeGraphicsItem::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
CustomGraphicsLineItem* parent_line_item = dynamic_cast<CustomGraphicsLineItem *>(parent_item);
if(parent_line_item == NULL)
{
return;
}
painter->setRenderHint(QPainter::Antialiasing);
QLineF parent_line = parent_line_item->line();
QLineF normal_vector_line = parent_line.normalVector();
normal_vector_line.setLength(20.0);
QPointF first_line_base_point = parent_line.pointAt(0.5);
QPointF _p1 = first_line_base_point -(normal_vector_line.p1()-normal_vector_line.p2());
QPointF _p2 = first_line_base_point +(normal_vector_line.p1()-normal_vector_line.p2());
QLineF rect_line_one = normal_vector_line;
rect_line_one.setP1(_p1);
rect_line_one.setP2(_p2);
qDebug() << "rect_line_one p1:" << rect_line_one.p1();
qDebug() << "rect_line_one p2:" << rect_line_one.p2();
QRectF image_rect( rect_line_one.p1(), QSize(30, 60));
painter->drawImage(image_rect, source_image);
}
QRectF PersonSizeGraphicsItem:: boundingRect() const
{
qreal extra = 0.0;
QRect rect = image_rect;
return QRectF(rect.topLeft(), QSizeF(rect.width(), rect.height()))
.normalized()
.adjusted(-extra, -extra, extra, extra);
}
QPainterPath PersonSizeGraphicsItem::shape() const
{
const int adjustment = 0.0;
QPainterPath path;
QRectF rect = boundingRect();
path.addRect(rect.adjusted(-adjustment, -adjustment, adjustment, adjustment));
return path;
}
Related
I am trying to resize a rectangle in paper.js. I am able to do it for older versions of paperjs (like 0.9.25) but it is not working for the latest version 0.11.8. I am not sure why this is happening, any help would be highly appreciated.
Here is the Sketch link, you may select the version to 0.9.25 where it works and 0.11.8 where it doesnt work.
Sketch
Here is my code:
var hitOptions = {
segments: true,
stroke: true,
fill: true,
tolerance: 1
};
project.currentStyle = {
fillColor: 'green',
strokeColor: 'black'
};
var rect_a = new Path.Rectangle(new Point(50, 50), 50);
var segment, path, hitType;
var clickPos = null;
var movePath = false;
var minHeight = 1;
var minWidth = 1;
function onMouseDown(event) {
segment = path = null;
var hitResult = project.hitTest(event.point, hitOptions);
if (!hitResult)
return;
hitType = hitResult.type;
if (event.modifiers.shift) {
if (hitResult.type == 'segment') {
hitResult.segment.remove();
};
return;
}
if (hitResult) {
path = hitResult.item;
if (hitResult.type == 'segment') {
segment = hitResult.segment;
}
}
movePath = hitResult.type == 'fill';
if (movePath) {
project.activeLayer.addChild(hitResult.item);
}
clickPos = checkHitPosition(event);
}
function onMouseMove(event) {
changeCursor(event);
project.activeLayer.selected = false;
if (event.item)
event.item.selected = true;
}
function onMouseDrag(event) {
if (hitType == "stroke" || hitType == "segment") {
resizeRectangle(path, event);
} else {
path.position += event.delta;
}
}
function resizeRectangle(path, event) {
switch(clickPos) {
case "SE" :
resizeBottom(path, event);
resizeRight(path, event);
break;
case "NE" :
resizeTop(path, event);
resizeRight(path, event);
break;
case "SW" :
resizeBottom(path, event);
resizeLeft(path, event);
break;
case "NW" :
resizeTop(path, event);
resizeLeft(path, event);
break;
case "S" :
resizeBottom(path, event);
break;
case "N" :
resizeTop(path, event);
break;
case "E" :
resizeRight(path, event);
break;
case "W" :
resizeLeft(path, event);
break;
}
}
function resizeTop(path, event) {
if(path.bounds.height >= minHeight) {
var adj = Math.min(event.delta.y, path.bounds.height-minHeight);
path.bounds.top += adj;
}
}
function resizeBottom(path, event) {
if(path.bounds.height >= minHeight) {
path.bounds.bottom += event.delta.y;
}
}
function resizeLeft(path, event) {
if(path.bounds.width >= minWidth) {
path.bounds.left += event.delta.x;
}
}
function resizeRight(path, event) {
if(path.bounds.width >= minWidth) {
path.bounds.right += event.delta.x;
}
}
function checkHitPosition(event) {
var hitResult = project.hitTest(event.point, hitOptions);
var clickPosition = null;
if (hitResult) {
if (hitResult.type == 'stroke' || hitResult.type == 'segment') {
var bounds = hitResult.item.bounds;
var point = hitResult.point;
if (bounds.top == point.y) {
clickPosition = "N";
}
if (bounds.bottom == point.y) {
clickPosition = "S";
}
if (bounds.left == point.x) {
clickPosition = "W";
}
if (bounds.right == point.x) {
clickPosition = "E";
}
if (bounds.top == point.y && bounds.left == point.x) {
clickPosition = "NW";
}
if (bounds.top == point.y && bounds.right == point.x) {
clickPosition = "NE";
}
if (bounds.bottom == point.y && bounds.left == point.x) {
clickPosition = "SW";
}
if (bounds.bottom == point.y && bounds.right == point.x) {
clickPosition = "SE";
}
} else {
clickPosition = "C";
}
}
return clickPosition;
};
function changeCursor(event) {
var hitPosition = checkHitPosition(event);
if(hitPosition == null ) {
document.body.style.cursor = "auto";
} else {
if (hitPosition == "C") {
document.body.style.cursor = "all-scroll";
} else {
document.body.style.cursor = hitPosition + "-resize";
}
}
}
helloworld,
If you want to resize/scale your path, I recommend using the Path.scalemethod (http://paperjs.org/reference/item/#scale-hor-ver).
To apply this on your example, replace your current resizing methods with:
function resizeTop(path, event) {
if(path.bounds.height >= minHeight) {
var relH = (event.point.y - (path.bounds.bottomCenter.y)) / path.bounds.height;
path.scale(1, -relH, path.bounds.bottomCenter)
}
}
function resizeBottom(path, event) {
if(path.bounds.height >= minHeight) {
var relH = (event.point.y - (path.bounds.topCenter.y)) / path.bounds.height;
path.scale(1, relH, path.bounds.topCenter)
}
}
function resizeLeft(path, event) {
if(path.bounds.width >= minWidth) {
var relW = (event.point.x - (path.bounds.rightCenter.x)) / path.bounds.width;
path.scale(-relW, 1, path.bounds.rightCenter)
}
}
function resizeRight(path, event) {
if(path.bounds.width >= minWidth) {
var relW = (event.point.x - (path.bounds.leftCenter.x)) / path.bounds.width;
path.scale(relW, 1, path.bounds.leftCenter)
}
}
Have a nice day!
-- edit --
I remade your sketch and replaced the code, sketch, which works with every version.
I wrote a Snake Game , when it hit it's tail , it will be Game Over and throw an alert. I set a Button in stage of my alert for new game , and i want to use that to run my cod again at first. is there any method or something...
It's my alert class
class alart {
public static void Game_over_alart(int dom) {
dom = (dom - 9) * 10 ;
Label sdom = new Label(Integer.toString(dom));
Stage window = new Stage();
window.setTitle("Game_Over");
Label gameOver = new Label("Game Over");
Label scor = new Label("SCORE : ");
Label best = new Label("BEST : ");
Text newgame = new Text("NEW GAME");
HBox hbox1 = new HBox(2, scor , sdom );
HBox hbox2 = new HBox(2, best);
VBox vbox = new VBox(2, hbox1, hbox2);
gameOver.setStyle(""
+ "-fx-alignment: top;"
+ "-fx-font-size: 40px;"
+ "-fx-font-style: italic;"
+ "-fx-font-weight: bold;"
+ "-fx-font-family: fantasy;"
+ "-fx-text-fill: lightgrey ;");
// + "-fx-background-color: gray");
DropShadow d = new DropShadow(5, Color.BLACK);
ScaleTransition st=new ScaleTransition(Duration.millis(100),newgame);
st.setToX(1.1);
st.setToY(1.1);
st.setFromX(1);
st.setFromY(1);
//st.setAutoReverse(true);
// st.setCycleCount(Animation.INDEFINITE);
gameOver.setEffect(d);
BorderPane b = new BorderPane();
b.setTop(gameOver);
b.setCenter(vbox);
b.setBottom(newgame);
gameOver.setAlignment(Pos.CENTER);
Scene s = new Scene(b, 400, 200);
window.setScene(s);
window.show();
window.setResizable(false);
newgame.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
}
});
newgame.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event1) {
st.play();
}
});
newgame.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event1) {
st.setFromX(1.1);
st.setFromY(1.1);
st.setToX(1);
st.setToY(1);
}
});
}
}
and it's the whole of my code
/**
* Created by Nadia on 12/31/2015.
*/
import javafx.animation.Animation;
import javafx.animation.AnimationTimer;
import javafx.animation.ScaleTransition;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.effect.DropShadow;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
import sun.jvm.hotspot.debugger.cdbg.Sym;
import javax.swing.text.StyledEditorKit;
import java.util.ArrayList;
public class Main_Snake extends Application{
Canvas canvas = new Canvas(399, 599);
Rectangle round = new Rectangle(0 ,0 , 400 , 600 );
B_Part snake = new Snake();
B_Part apple = new Apple();
B_Part mane = new Mane();
#Override
public void start(Stage primaryStage) throws Exception {
round.setStroke(Color.BLACK);
round.setFill(Color.WHITE);
StackPane ss = new StackPane();
ss.getChildren().addAll(round, canvas);
BorderPane b = new BorderPane();
b.setBottom(ss);
Scene scene = new Scene(b, 410, 700);
primaryStage.setScene(scene);
primaryStage.setTitle ( "Snake" );
primaryStage.show();
primaryStage.setResizable(false);
play();
}
public void play() {
AnimationTimer timer = new AnimationTimer() {
private long lastUpdate = 0;
#Override
public void handle(long now) {
if (now - lastUpdate >= 20_000_000) { // payin avordane sor#
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.WHITE);
gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
try {
for ( int i = 0 ; i < 5 ; i++)
mane.Move(canvas.getScene());
} catch (Game_Over_Exception e) {
}finally {
mane.Drow(canvas);
}
try {
apple.Move(canvas.getScene());
}catch (Exception e) {
}finally {
apple.Drow(canvas);
}
try {
snake.Move(canvas.getScene());
} catch (Game_Over_Exception e) {
stop();
alart.Game_over_alart(snake.X.size());
}finally {
snake.Drow(canvas); // har bar mar rasm mishe bad az move va ye sib ba X,Y khodesh rasm mishe tu tabe move dar morede tabe Point hast
}
lastUpdate = now; // sor#
}
}
};
timer.start();
}
}
abstract class B_Part {
boolean goNorth = true, goSouth = false, goWest = false, goEast = false; ///////////////////////////////////////////////////////
static int GM = 0 ;
int Mx , My ;
static ArrayList<Integer> Mane_x = new ArrayList<>();
static ArrayList<Integer> Mane_y = new ArrayList<>();
static int x, y ; // marbut be apple
static int j = 0;
// int gm_ov = 0; // vase game over shodan
static ArrayList<Integer> X = new ArrayList<>();
static ArrayList<Integer> Y = new ArrayList<>();
static int Domx1 =400 , Domy1 =390 ;
static int Domx2 =400, Domy2 =400 ;
abstract public void Drow(Canvas canvas);
abstract public void Move(Scene scene)throws Game_Over_Exception;
void Point() {
if (X.get(0) == x && Y.get(0) == y)
j = 0;
}
void Game_Over() {
for (int i = 1 ; i < X.size() ; i ++) { // inke mokhtasate sare mar tu mokhtasate tanesh hast ya na
if (X.get(0).equals(X.get(i)) && Y.get(0).equals(Y.get(i))) {
GM = 1;
}
}
for (int i = 0 ; i < Mane_x.size() ; i ++) { // inke mokhtasate sare mar be mane hast ya na
if (X.get(0).equals(Mane_x.get(i)) && Y.get(0).equals(Mane_y.get(i))) {
GM = 1;
}
}
}
}
class Apple extends B_Part {
#Override
public void Move(Scene scene) {
if (j == 0) { // ye sib bede ke ru mar nabashe ( rasmesh tu rasme )
do {
x = (int) ( Math.random() * 390 + 1 );
y = (int) ( Math.random() * 590 + 1 );
} while (X.indexOf(x) != -1 && Y.get(X.indexOf(x)) == y || x % 10 != 0 || y % 10 != 0);
/*
inja aval chek kardam tu araylist x hast ya na ag bud sharte aval ok hala sharte do ke tu Y ham mibinim tu hamun shomare khune
y barabare y mast ag bud pas ina bar ham montabeghan va sharte dovom ham ok . 2 sharte akhar ham vase ine ke mare ma faghat mazrab
haye 10 and pas ta vaghti in se shart bargharare jahayie ke ma nemikhaym va hey jaye dg mide
*/
j = 1;
}
}
#Override
public void Drow(Canvas canvas) {
DropShadow dd = new DropShadow(20,Color.RED);
GraphicsContext a = canvas.getGraphicsContext2D();
a.setFill(Color.RED);
a.setEffect(dd);
a.fillRect( x , y , 9 ,9);
a.setEffect(null);
}
}
class Snake extends B_Part {
Snake() { //cunstructor
X.add(400);
Y.add(300);
X.add(400);
Y.add(310);
X.add(400);
Y.add(320);
X.add(400);
Y.add(330);
X.add(400);
Y.add(340);
X.add(400);
Y.add(350);
X.add(400);
Y.add(360);
X.add(400);
Y.add(370);
X.add(400);
Y.add(380);
}
#Override
public void Drow(Canvas canvas) {
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.BLACK);
// keshidane mar (body yeki ezafe tar az adade morabaA mide)
for (int i = X.size() - 1; i >= 0; i--) {
gc.fillRect(X.get(i), Y.get(i), 9, 9);
gc.setStroke(Color.WHITE);
}
}
#Override
public void Move(Scene scene) throws Game_Over_Exception {
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent small) {
switch (small.getText()) {
case "W":
if (!goSouth) {
goNorth = true;
goSouth = false;
goWest = false;
goEast = false;
}
break;
case "w":
if (!goSouth) {
goNorth = true;
goSouth = false;
goWest = false;
goEast = false;
}
break;
case "S":
if (!goNorth) {
goSouth = true;
goNorth = false;
goWest = false;
goEast = false;
}
break;
case "s":
if (!goNorth) {
goSouth = true;
goNorth = false;
goWest = false;
goEast = false;
}
break;
case "A":
if (!goEast) {
goWest = true;
goEast = false;
goSouth = false;
goNorth = false;
}
break;
case "a":
if (!goEast) {
goWest = true;
goEast = false;
goSouth = false;
goNorth = false;
}
break;
case "D":
if (!goWest) {
goEast = true;
goWest = false;
goSouth = false;
goNorth = false;
}
break;
case "d":
if (!goWest) {
goEast = true;
goWest = false;
goSouth = false;
goNorth = false;
}
break;
}
}
});
/* scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent e) {
switch (e.getCode()) {
case UP:
if (!goSouth) {
goNorth = true;
goSouth = false;
goWest = false;
goEast = false;
}
break;
case DOWN:
if (!goNorth) {
goSouth = true;
goNorth = false;
goWest = false;
goEast = false;
}
break;
case LEFT:
if (!goEast) {
goWest = true;
goEast = false;
goSouth = false;
goNorth = false;
}
break;
case RIGHT:
if (!goWest) {
goEast = true;
goWest = false;
goSouth = false;
goNorth = false;
}
break;
}
}
});
*/
Domx1 = X.get(X.size() - 1);
Domy1 = Y.get(Y.size() - 1);
for (int z = X.size() - 1; z > 0; z--) {
X.remove(z);
X.add(z, X.get(z - 1));
Y.remove(z);
Y.add(z, Y.get(z - 1));
}
if (goNorth) {
Y.add(0, Y.get(0) - 10);
Y.remove(1);
}
if (goSouth) {
Y.add(0, Y.get(0) + 10);
Y.remove(1);
}
if (goEast) {
X.add(0, X.get(0) + 10);
X.remove(1);
}
if (goWest) {
X.add(0, X.get(0) - 10);
X.remove(1);
}
Point(); // emtiaz gerefte
if (j == 0) {
X.add(Domx1);
Y.add(Domy1);
X.add(Domx2);
Y.add(Domy2);
Domx2 = Domx1;
Domy2 = Domy1;
System.out.println();
System.out.println("size : "+Mane_x.size() );
System.out.print(" clear : " );
Mane_x.clear();
Mane_y.clear();
System.out.println("size : "+Mane_x.size() );
}
Game_Over();
if ( GM == 1 ) {
throw new Game_Over_Exception("Game Over");
}
if (X.get(0) > 390) {
X.remove(0);
X.add(0, 0);
}
if (X.get(0) < 0) {
X.remove(0);
X.add(0, 400);
}
if (Y.get(0) > 590) {
Y.remove(0);
Y.add(0, 0);
}
if (Y.get(0) < 0) {
Y.remove(0);
Y.add(0, 600);
}
}
}
class Mane extends B_Part{
#Override
public void Drow(Canvas canvas) {
GraphicsContext gc = canvas.getGraphicsContext2D();
for ( int i = 0 ; i < Mane_x.size() ; i++) {
gc.setFill(Color.GRAY);
gc.fillRect(Mane_x.get(i), Mane_y.get(i), 9, 9);
}
//System.out.println(Mane_x.get(i)+" "+Mane_y.get(i));}
}
#Override
public void Move(Scene scene) {
if (j == 0) { // ye sib bede ke ru mar nabashe ( rasmesh tu rasme )
do {
Mx = (int) (Math.random() * 390 + 1);
My = (int) (Math.random() * 590 + 1);
} while (Mx == x && My == y ||
Mane_x.indexOf(Mx) != -1 && Mane_y.get(Mane_x.indexOf(Mx)) == My ||
X.indexOf(Mx) != -1 && Y.get(X.indexOf(Mx)) == My ||
Mx % 10 != 0 || My % 10 != 0
/* Mx == X.get(0) + 10 && My == Y.get(0) || // yeki joloye saresh nayofte (vaghti rast mire)
Mx == X.get(0) - 10 && My == Y.get(0) || // ( vaghti chap mire)
Mx == X.get(0) && My == Y.get(0) + 10 || // yek ta jolo tar az saresh nayofte vaghtti payi
Mx == X.get(0) && My == Y.get(0) - 10*/); // vaghti bala
//sharte chek kardane in ke har maneye random rooye mar ya maneye ghablia nayofte ( sib hamintor )
Mane_x.add(Mx);
Mane_y.add(My);
}
}
}
class Game_Over_Exception extends Exception{
public Game_Over_Exception (String s){
super(s);
}
}
Hand over a restart method to the alert handler. You can do that directly or via interface, e. g.:
public interface GameManager {
public void restart();
}
Your main class must implement that interface:
public class Main_Snake extends Application implements GameManager {
public void restart() {
// TODO: reset playfield & restart game
}
public void play() {
...
try {
snake.Move(canvas.getScene());
} catch (Game_Over_Exception e) {
stop();
alart.Game_over_alart(snake.X.size(), Main_Snake.this);
}
...
}
}
And in your alart class you invoke that method:
class alart {
public static void Game_over_alart(int dom, GameManager gameManager) {
...
newgame.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
// TODO: close dialog
// restart game
gameManager.restart();
}
});
...
}
}
I have an arc inherited from QGraphicsItem, which is making use of virtual clone() to allow the editing operations i.e cut, copy and paste. When the arc is pasted/cloned it is displaced from the correct positions (using the context menu position). Here is my Arc class as well as the clone() function:
#include "arc.h"
#include "qmath.h"
#include <QPen>
#include <QPainterPath>
Arc::Arc(int i, QPointF point1, QPointF point2, QPointF point3)
{
id = i;
p1 = point1;
p2 = point2;
p3 = point3;
init();
}
int Arc::type() const
{
// Enable the use of qgraphicsitem_cast with arc item.
return Type;
}
Arc::Arc(QPointF point1, QPointF point2, QPointF point3)
{
p1 = point1;
p2 = point2;
p3 = point3;
p1 = QPointF(0,0);
p2 = QPointF(0,1);
p3 = QPointF(1,1);
init();
}
// Calculates startangle and spanangle
void Arc::init()
{
lineBC = QLineF(p2, p3);
lineAC = QLineF(p1, p3);
lineBA = QLineF(p2, p1);
rad = qAbs(lineBC.length()/(2 * qSin(qDegreesToRadians
(lineAC.angleTo(lineBA)))));
bisectorBC = QLineF(lineBC.pointAt(0.5), lineBC.p2());
bisectorBC.setAngle(lineBC.normalVector().angle());
bisectorBA = QLineF(lineBA.pointAt(0.5), lineBA.p2());
bisectorBA.setAngle(lineBA.normalVector().angle());
bisectorBA.intersect(bisectorBC, ¢er);
circle = QRectF(center.x() - rad, center.y() - rad, rad * 2, rad * 2);
lineOA = QLineF(center, p1);
lineOB = QLineF(center, p2);
lineOC = QLineF(center, p3);
startAngle = lineOA.angle();
spanAngle = lineOA.angleTo(lineOC);
/**
* Make sure that the span angle covers all three points with the
* second point in the middle
*/
if (qAbs(spanAngle) < qAbs(lineOA.angleTo(lineOB)) ||
qAbs(spanAngle) < qAbs(lineOB.angleTo(lineOC)))
{
// swap the end point and invert the spanAngle
startAngle = lineOC.angle();
spanAngle = 360 - spanAngle;
}
int w = 10;
boundingRectTemp = circle.adjusted(-w, -w, w, w);
}
QRectF Arc::boundingRect() const
{
// outer most edges
return boundingRectTemp;
}
void Arc::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
QPen paintpen;
painter->setRenderHint(QPainter::Antialiasing);
paintpen.setWidth(1);
// Draw arc
if (isSelected())
{
// sets brush for end points
painter->setBrush(Qt::SolidPattern);
paintpen.setColor(Qt::red);
painter->setPen(paintpen);
painter->drawEllipse(p1, 2, 2);
painter->drawEllipse(p2, 2, 2);
painter->drawEllipse(p3, 2, 2);
// sets pen for arc path
paintpen.setStyle(Qt::DashLine);
paintpen.setColor(Qt::black);
painter->setPen(paintpen);
}
else
{
painter->setBrush(Qt::SolidPattern);
paintpen.setColor(Qt::black);
painter->setPen(paintpen);
painter->drawEllipse(p1, 2, 2);
painter->drawEllipse(p2, 2, 2);
painter->drawEllipse(p3, 2, 2);
}
QPainterPath path;
path.arcMoveTo(circle, startAngle);
path.arcTo(circle, startAngle, spanAngle);
painter->setBrush(Qt::NoBrush);
painter->drawPath(path);
}
getEntity *Arc::clone()
{
Arc *a = new Arc;
a->p1 = p1;
a->p2 = p2;
a->p3 = p3;
a->lineAC = AC;
a->lineBA = lineBA;
a->lineBC = lineBC;
a->lineOA = lineOA;
a->lineOB = lineOB;
a->lineOC = lineOC;
a->bisectorBA = bisectorBA;
a->bisectorBC = bisectorBC;
a->center = center;
a->circle = circle;
a->startAngle = startAngle;
a->spanAngle = spanAngle;
return a;
}
#ifndef GETENTITY_H
#define GETENTITY_H
#include <QGraphicsItem>
class getEntity : public QObject, public QGraphicsItem
{
public:
getEntity(QObject *parent = 0) : QObject(parent) {}
virtual ~getEntity() {}
virtual getEntity *clone(int i)
{
return 0;
}
int id;
};
#endif // GENTITY_H
I have a png image which is displayed on the graphics scene as a QGraphicsPixmapItem.
The image is rectangular in shape. I need to resize the png image every time it is dragged by a mouse move event on any side of the rectangle ie, from left,right,top or bottom.
Currently I am able to resize the image only when dragged from right and bottom sides only. Image resizing fails when dragged from left and top side. Please let me know the mistakes in my code below. Here Resizing is based on original image file which is of maximum size, but the initial image displayed on the scene itself is a scaled down version of source image.
The partial code is posted below, I have not shown hoverEnterEvent() implementation:
PersonSizeGraphicsItem::PersonSizeGraphicsItem(const QPixmap &pixmap, QGraphicsScene *scene)
:QGraphicsPixmapItem(pixmap, 0, scene)
{
this->setFlag(QGraphicsItem::ItemIsMovable, true);
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setFocus(Qt::MouseFocusReason);
this->setAcceptHoverEvents(true);
//this->setScale(0.5);
rect_left_condition = false;
rect_right_condition = false;
rect_top_condition = false;
rect_bottom_condition = false;
rect_resize_occurred = false;
image_rect = QRect();
image_rect = this->pixmap().toImage().rect();
}
PersonSizeGraphicsItem::~PersonSizeGraphicsItem()
{
}
int PersonSizeGraphicsItem::type() const
{
return item_type;
}
void PersonSizeGraphicsItem::setSourceImage(const QImage& source_image)
{
this->source_image = source_image;
}
void PersonSizeGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
const QPointF event_pos = event->pos();
const QPointF event_scene_pos = event->scenePos();
QPoint current_top_left = image_rect.topLeft();
QPoint current_bottom_right = image_rect.bottomRight();
if((event->scenePos().x() > this->scene()->width()) || (event->scenePos().y() > this->scene()->height())
|| (event->scenePos().x() < 0) || (event->scenePos().y() < 0) )
{
return;
}
if( this->cursor().shape() == Qt::SizeHorCursor )
{
if(rect_right_condition)
{
image_rect = QRect( current_top_left, QPoint( event->pos().x(), current_bottom_right.y()) );
rect_resize_occurred = true;
}
if(rect_left_condition)
{
image_rect = QRect( QPoint(event_pos.x(), 0), current_bottom_right );
QPoint new_top_left = image_rect.topLeft();
QPointF mapped_topLeft = mapToParent(QPointF(new_top_left.x(),new_top_left.y()));
this->setPos(mapped_topLeft);
rect_resize_occurred = true;
//qDebug() << "new rectangle top left:" << this->pixmap().rect().topLeft();
}
}
if( this->cursor().shape() == Qt::SizeVerCursor )
{
if(rect_bottom_condition)
{
image_rect = QRect(current_top_left, QPoint(current_bottom_right.x(), event->pos().y()));
rect_resize_occurred = true;
}
if(rect_top_condition)
{
image_rect = QRect(QPoint(0, event_pos.y()), current_bottom_right);
QPoint new_top_left = image_rect.topLeft();
QPointF mapped_topLeft = mapToParent(QPointF(new_top_left.x(),new_top_left.y()));
this->setPos(mapped_topLeft);
qDebug() << "new rectangle top left###:" << this->pixmap().rect().topLeft();
rect_resize_occurred = true;
}
}
this->update();
}
void PersonSizeGraphicsItem::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->drawImage(image_rect, source_image);
}
QRectF PersonSizeGraphicsItem:: boundingRect() const
{
qreal extra = 0.0;
QRect rect = image_rect;
return QRectF(rect.topLeft(), QSizeF(rect.width(), rect.height()))
.normalized()
.adjusted(-extra, -extra, extra, extra);
}
I tried the following code to resize the rectangle and it works. In the earlier version of mouseMoveEvent(), I always tried to smehow set the topLeft coordinates to (0,0) each time after resize is done.
In the new version, I let the topLeft coordinates remain where they are and not bother to set the topLeft to (0,0) after each resize. Once the resize is done, the topLeft is never set to origin here in local coordinates.
void PersonSizeGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
const QPointF event_pos = event->pos();
const QPointF event_scene_pos = event->scenePos();
QPoint current_top_left = image_rect.topLeft();
QPoint current_bottom_right = image_rect.bottomRight();
if((event->scenePos().x() > this->scene()->width()) || (event->scenePos().y() > this->scene()->height())
|| (event->scenePos().x() < 0) || (event->scenePos().y() < 0) )
{
return;
}
if( this->cursor().shape() == Qt::SizeHorCursor )
{
if(rect_right_condition)
{
image_rect = QRect( current_top_left, QPoint( event->pos().x(), current_bottom_right.y()) );
if( image_rect.width() <=8 || image_rect.height() <=24 )
{
return;
}
rect_resize_occurred = true;
}
if(rect_left_condition)
{
//image_rect = QRect( QPoint(event_pos.x(), 0), current_bottom_right );
image_rect = QRect( QPoint(event_pos.x(), current_top_left.y()), current_bottom_right );
if( image_rect.width() <=8 || image_rect.height() <=24 )
{
return;
}
rect_resize_occurred = true;
/* QPoint new_top_left = image_rect.topLeft();
QPointF mapped_topLeft = mapToParent(QPointF(new_top_left.x(),new_top_left.y()));
this->setPos(mapped_topLeft); */
//qDebug() << "new rectangle top left:" << this->pixmap().rect().topLeft();
}
}
if( this->cursor().shape() == Qt::SizeVerCursor )
{
if(rect_bottom_condition)
{
image_rect = QRect(current_top_left, QPoint(current_bottom_right.x(), event->pos().y()));
if( image_rect.width() <=8 || image_rect.height() <=24 )
{
return;
}
rect_resize_occurred = true;
}
if(rect_top_condition)
{
//image_rect = QRect(QPoint(0, event_pos.y()), current_bottom_right);
image_rect = QRect(QPoint(current_top_left.x(), event_pos.y()), current_bottom_right);
if( image_rect.width() <=8 || image_rect.height() <=24 )
{
return;
}
/* QPoint new_top_left = image_rect.topLeft();
QPointF mapped_topLeft = mapToParent(QPointF(new_top_left.x(),new_top_left.y()));
this->setPos(mapped_topLeft); */
rect_resize_occurred = true;
}
}
this->update();
}
I have to make scrollbar with handle of fixed size since its background image becomes ugly when being scaled. I use the following style sheet:
QScrollBar::handle:vertical {
border-image:url(:/images/handle.png);
min-height: 47px;
max-height: 47px;
height: 47px;
width:10px;
}
but it seems like max-height isn't valid property. How to prevent handle scaling?
Little trick, from Qt source code:
myScrollbar.h
class myScrollBar : public QScrollBar
{
Q_OBJECT
public:
myScrollBar(Qt::Orientation orientation, QWidget *parent = 0);
void setSliderLength(int length);
protected:
void paintEvent(QPaintEvent *);
private:
QRect subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, /*const*/ QWidget *widget);
QRect visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect);
int sliderPositionFromValue(int min, int max, int logicalValue, int span, bool upsideDown);
private:
int _sliderLength;
};
myScrollbar.cpp
myScrollBar::myScrollBar(Qt::Orientation orientation, QWidget *parent)
: QScrollBar(orientation, parent),
_sliderLength(100)
{
}
void myScrollBar::paintEvent(QPaintEvent *e)
{
qDebug() << "scrollbar paintevent";
//Q_D(QScrollBar);
QScrollBar::paintEvent(e);
QPainter painter(this);
QStyleOptionSlider opt;
initStyleOption(&opt);
opt.subControls = QStyle::SC_All;
QWidget *widget = this;
// if (d->pressedControl) {
// opt.activeSubControls = (QStyle::SubControl)d->pressedControl;
// if (!d->pointerOutsidePressedControl)
// opt.state |= QStyle::State_Sunken;
// } else {
// opt.activeSubControls = (QStyle::SubControl)d->hoverControl;
// }
QPainter *p = &painter;
//style()->drawComplexControl(QStyle::CC_ScrollBar, &opt, &p, this);
if (const QStyleOptionSlider *scrollbar = &opt) {
// Make a copy here and reset it for each primitive.
QStyleOptionSlider newScrollbar = *scrollbar;
QStyle::State saveFlags = scrollbar->state;
if (scrollbar->subControls & QStyle::SC_ScrollBarSubLine) {
newScrollbar.state = saveFlags;
newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarSubLine, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarSubLine))
newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver);
style()->drawControl(QStyle::CE_ScrollBarSubLine, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & QStyle::SC_ScrollBarAddLine) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarAddLine, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarAddLine))
newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver);
style()->drawControl(QStyle::CE_ScrollBarAddLine, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & QStyle::SC_ScrollBarSubPage) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarSubPage, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarSubPage))
newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver);
style()->drawControl(QStyle::CE_ScrollBarSubPage, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & QStyle::SC_ScrollBarAddPage) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarAddPage, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarAddPage))
newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver);
style()->drawControl(QStyle::CE_ScrollBarAddPage, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & QStyle::SC_ScrollBarFirst) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarFirst, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarFirst))
newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver);
style()->drawControl(QStyle::CE_ScrollBarFirst, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & QStyle::SC_ScrollBarLast) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
newScrollbar.rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarLast, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarLast))
newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver);
style()->drawControl(QStyle::CE_ScrollBarLast, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & QStyle::SC_ScrollBarSlider) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
QRect rect = subControlRect(QStyle::CC_ScrollBar, &newScrollbar, QStyle::SC_ScrollBarSlider, widget);
newScrollbar.rect = QRect(rect.topLeft(), QSize(rect.width(), 100));
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & QStyle::SC_ScrollBarSlider))
newScrollbar.state &= ~(QStyle::State_Sunken | QStyle::State_MouseOver);
style()->drawControl(QStyle::CE_ScrollBarSlider, &newScrollbar, p, widget);
if (scrollbar->state & QStyle::State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(newScrollbar);
fropt.rect.setRect(newScrollbar.rect.x() + 2, newScrollbar.rect.y() + 2,
newScrollbar.rect.width() - 5,
newScrollbar.rect.height() - 5);
style()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, p, widget);
}
}
}
}
}
void myScrollBar::setSliderLength(int length)
{
_sliderLength = length;
}
QRect myScrollBar::subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QStyle::SubControl sc, /*const*/ QWidget *widget)
{
QRect ret;
switch (cc) {
case QStyle::CC_ScrollBar:
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
const QRect scrollBarRect = scrollbar->rect;
int sbextent = 0;
if (!style()->styleHint(QStyle::SH_ScrollBar_Transient, scrollbar, widget))
sbextent = style()->pixelMetric(QStyle::PM_ScrollBarExtent, scrollbar, widget);
int maxlen = ((scrollbar->orientation == Qt::Horizontal) ?
scrollBarRect.width() : scrollBarRect.height()) - (sbextent * 2);
int sliderlen;
// calculate slider length
if (scrollbar->maximum != scrollbar->minimum) {
uint range = scrollbar->maximum - scrollbar->minimum;
sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep);
int slidermin = style()->pixelMetric(QStyle::PM_ScrollBarSliderMin, scrollbar, widget);
if (_sliderLength < slidermin || range > INT_MAX / 2)
_sliderLength = slidermin;
if (_sliderLength > maxlen)
_sliderLength = maxlen;
//length of the slider
sliderlen = _sliderLength;
} else {
sliderlen = maxlen;
}
int sliderstart = sbextent + this->sliderPositionFromValue(scrollbar->minimum,
scrollbar->maximum,
scrollbar->sliderPosition,
maxlen - sliderlen,
scrollbar->upsideDown);
switch (sc) {
case QStyle::SC_ScrollBarSubLine: // top/left button
if (scrollbar->orientation == Qt::Horizontal) {
int buttonWidth = qMin(scrollBarRect.width() / 2, sbextent);
ret.setRect(0, 0, buttonWidth, scrollBarRect.height());
} else {
int buttonHeight = qMin(scrollBarRect.height() / 2, sbextent);
ret.setRect(0, 0, scrollBarRect.width(), buttonHeight);
}
break;
case QStyle::SC_ScrollBarAddLine: // bottom/right button
if (scrollbar->orientation == Qt::Horizontal) {
int buttonWidth = qMin(scrollBarRect.width()/2, sbextent);
ret.setRect(scrollBarRect.width() - buttonWidth, 0, buttonWidth, scrollBarRect.height());
} else {
int buttonHeight = qMin(scrollBarRect.height()/2, sbextent);
ret.setRect(0, scrollBarRect.height() - buttonHeight, scrollBarRect.width(), buttonHeight);
}
break;
case QStyle::SC_ScrollBarSubPage: // between top/left button and slider
if (scrollbar->orientation == Qt::Horizontal)
ret.setRect(sbextent, 0, sliderstart - sbextent, scrollBarRect.height());
else
ret.setRect(0, sbextent, scrollBarRect.width(), sliderstart - sbextent);
break;
case QStyle::SC_ScrollBarAddPage: // between bottom/right button and slider
if (scrollbar->orientation == Qt::Horizontal)
ret.setRect(sliderstart + sliderlen, 0,
maxlen - sliderstart - sliderlen + sbextent, scrollBarRect.height());
else
ret.setRect(0, sliderstart + sliderlen, scrollBarRect.width(),
maxlen - sliderstart - sliderlen + sbextent);
break;
case QStyle::SC_ScrollBarGroove:
if (scrollbar->orientation == Qt::Horizontal)
ret.setRect(sbextent, 0, scrollBarRect.width() - sbextent * 2,
scrollBarRect.height());
else
ret.setRect(0, sbextent, scrollBarRect.width(),
scrollBarRect.height() - sbextent * 2);
break;
case QStyle::SC_ScrollBarSlider:
if (scrollbar->orientation == Qt::Horizontal)
ret.setRect(sliderstart, 0, sliderlen, scrollBarRect.height());
else
ret.setRect(0, sliderstart, scrollBarRect.width(), sliderlen);
break;
default:
break;
}
ret = visualRect(scrollbar->direction, scrollBarRect, ret);
}
return ret;
}
}
QRect myScrollBar::visualRect(Qt::LayoutDirection direction, const QRect &boundingRect, const QRect &logicalRect)
{
if (direction == Qt::LeftToRight)
return logicalRect;
QRect rect = logicalRect;
rect.translate(2 * (boundingRect.right() - logicalRect.right()) +
logicalRect.width() - boundingRect.width(), 0);
return rect;
}
int myScrollBar::sliderPositionFromValue(int min, int max, int logicalValue, int span, bool upsideDown)
{
if (span <= 0 || logicalValue < min || max <= min)
return 0;
if (logicalValue > max)
return upsideDown ? span : min;
uint range = max - min;
uint p = upsideDown ? max - logicalValue : logicalValue - min;
if (range > (uint)INT_MAX/4096) {
double dpos = (double(p))/(double(range)/span);
return int(dpos);
} else if (range > (uint)span) {
return (2 * p * span + range) / (2*range);
} else {
uint div = span / range;
uint mod = span % range;
return p * div + (2 * p * mod + range) / (2 * range);
}
// equiv. to (p * span) / range + 0.5
// no overflow because of this implicit assumption:
// span <= 4096
}
eg:
myScrollBar *bar = new myScrollBar(Qt::Vertical, ui->treeWidget);
ui->treeWidget->setVerticalScrollBar(bar);
Use
this jquery plugin http://jscrollpane.kelvinluck.com/