Форум сайта python.su
Добрый день, всем.
Появилась мысль научиться рисовать на рабочем столе. К примеру, линию под курсором мыши или прямоугольную область (подобно выделению). Вот только незнаю с чего начать. Пробовал гуглить – находил обрывки кода на Delphi. На Python ничего..
Как я понимаю, нужно получить объект desktop'a и с помощью QPainter'a рисовать на нем?
QtGui.QApplication.desktop() это и есть то, что мне нужно? Или всетаки нет?
Написал вот такое (точнее собрал из нескольких найденных скриптов). Пока рисование на виджете
# -*- coding: cp1251 -*-
from PyQt4 import QtCore, QtGui
import sys
import os
class MainForm(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.scribbling = False
self.myPenWidth = 1
self.myPenColor = QtCore.Qt.blue
self.lastPoint = QtCore.QPoint()
def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.lastPoint = event.pos()
self.scribbling = True
def mouseMoveEvent(self, event):
if (event.buttons() & QtCore.Qt.LeftButton) and self.scribbling:
self.drawLineTo(event.pos())
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton and self.scribbling:
self.drawLineTo(event.pos())
self.scribbling = False
def drawLineTo(self, endPoint):
painter = QtGui.QPainter()
painter.begin(self)
painter.setPen(QtGui.QPen(self.myPenColor, self.myPenWidth, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
painter.drawLine(self.lastPoint, endPoint)
painter.end()
rad = self.myPenWidth / 2 + 2
self.update(QtCore.QRect(self.lastPoint, endPoint).normalized().adjusted(-rad, -rad, +rad, +rad))
self.lastPoint = QtCore.QPoint(endPoint)
class App(QtGui.QApplication):
def __init__(self, *args):
QtGui.QApplication.__init__(self, *args)
self.ui = MainForm(None)
self.ui.show()
if __name__ == "__main__":
app = App(sys.argv)
app.exec_()
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active
QPainter::end: Painter not active, aborted
Офлайн
Я правда никогда не рисовал на рабочем столе, но попробуй посмотреть в сторону QDesktopWidget.
Офлайн
pasaranax, QDesktopWidget может и то, что нужно
QWidget * QDesktopWidget::screen ( int screen = -1 )Но я всеравно не могу догнать, как правильно написать. Пишу так
Returns a widget that represents the screen with index screen. This widget can be used to draw directly on the desktop, using an unclipped painter like this:
QPainter paint( QApplication::desktop()->screen( 0 ), TRUE );
paint.draw…
…
paint.end();
def drawLineTo(self, endPoint):
painter = QtGui.QPainter()
painter.begin(QtGui.QApplication.desktop().screen())
painter.setPen(QtGui.QPen(self.myPenColor, self.myPenWidth, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
painter.drawLine(self.lastPoint, endPoint)
painter.end()
def drawLineTo(self, endPoint):
painter = QtGui.QPainter()
painter.begin(QtGui.QApplication.desktop().screen(), True)
painter.setPen(QtGui.QPen(self.myPenColor, self.myPenWidth, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
painter.drawLine(self.lastPoint, endPoint)
painter.end()
Офлайн
Максимум, чего получилось достичь, это создание прозначного виджета, на котором можно рисовать. Вот простейший пример:
#!/usr/bin/env python2.6
# coding: utf-8
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Widget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
def paintEvent(self, event):
painter = QPainter(self)
painter.setBrush(Qt.blue)
painter.drawEllipse(0, 0, 100, 100)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Widget()
w.resize(105, 105)
w.show()
sys.exit(app.exec_())
Отредактировано (Ноя. 22, 2009 17:16:30)
Офлайн
pasaranax
Тема, конечно, интересная. Ссылки посмотрел – интересно, спасибо.
Вообще я об этом задумался, когда в очередной раз увидел программу для снятия скриншотов, в которой можно выделять произвольную область.
Как это сделать, кроме как рисованием на экране? Нарисовать прозрачный виджет, перед тем как рисовать выделение?
Займусь этим как проект закончится…
Офлайн
А можно ссылку на эту программу?
Офлайн
pasaranax, даже незнаю как она называется :) не пользуюсь я такими, потому как скриншоты делаю ооочень редко. А вот шеф мой скриншоты очень любит, у него ее и увидел. Узнаю как называется и вечером выложу
Офлайн
http://habrahabr.ru/blogs/habraware/57587
у самого давно тайная мечта сделать что-то аналогичное с заливкой на имейджзхак или что-то подобное.
Отредактировано (Ноя. 24, 2009 08:34:30)
Офлайн
Да, програмулька наподобие: включил, выделил область, сохранил на диск.
+ Такое встречается в разных приложениях. Недавно пришлось написать небольшой хепл с помощью Help&Manual5, там есть такая же возможность делать скрины: при включении этой возможности, около курсора появляется маленькое окошко с координатами. при этом можно делать все что угодно (двигать окна, менять размеры, печатать)…Зажал Ctrl и кликнул – делается снимок. Вот как они такое реализуют? Что за технология такая? :)
Офлайн
Всем снова здрасте.
Вот чего удалось добиться по теме “Рисование на рабочем столе”. К Qt это отношение уже в принципе не имеет, но раз началали здесь, то тут и продолжу. Да и гуй ко всему этому напишу всеравно на Qt
# -*- coding: cp1251 -*-
from pythoncom import PumpMessages
from pyHook import HookManager
import win32gui
from win32con import PS_SOLID
import win32con
import win32api
global scribbling, lastPoint, controlDown
def OnKeyboardEvent(event):
global scribbling, lastPoint, controlDown
if event.GetMessageName() == 'key down' and event.Key in ['Lcontrol', 'Rcontrol']:
controlDown = True
elif event.GetMessageName() == 'key up' and event.Key in ['Lcontrol', 'Rcontrol']:
controlDown = False
return True # False делать опасно! Скрипт НЕ передаст сигнал системе
def OnMouseDown(event):
global scribbling, lastPoint
if event.GetMessageName() == 'mouse left down' and controlDown:
lastPoint = event.Position
scribbling = True
return False
return True
def OnMouseUp(event):
global scribbling
if event.GetMessageName() == 'mouse left up' and scribbling:
drawLineTo(event.Position)
scribbling = False
return True
def OnMouseMove(event):
global scribbling
if scribbling:
drawLineTo(event.Position)
# return False
return True
def drawLineTo(endPoint):
global lastPoint
x1,y1 = lastPoint
x2,y2 = endPoint
lastPoint = endPoint
clRed = 0x0000ED # Цвет для рисования
# Получаем контекст экрана рабочего стола
screenDC = win32gui.GetDC(None)
# Создаем новые карандаш и кисть
penHandle = win32gui.CreatePen(PS_SOLID, 1, clRed)
oldPenHandle = win32gui.SelectObject(screenDC, penHandle)
brushHandle = win32gui.CreateSolidBrush(clRed)
oldBrushHandle = win32gui.SelectObject(screenDC, brushHandle)
# Рисуем на рабочем столе
""" Рисование прямоугольника
left = 100
top = 100
width = 200
height = 300
win32gui.Rectangle(screenDC, left, top, left+width, top + height)
# """
win32gui.MoveToEx(screenDC,x1, y1)
win32gui.LineTo(screenDC,x2,y2)
# Освобождаем память от карандаша, кисти и указателя на рабочий стол
win32gui.SelectObject(screenDC, oldBrushHandle)
win32gui.DeleteObject(brushHandle)
win32gui.SelectObject(screenDC, oldPenHandle)
win32gui.DeleteObject(penHandle)
win32gui.ReleaseDC(0, screenDC)
scribbling = False
lastPoint = None
controlDown = False
hookm = HookManager()
# Определям функцию на перехват
hookm.MouseLeftDown = OnMouseDown
hookm.MouseLeftUp = OnMouseUp
hookm.MouseMove = OnMouseMove
# Определям функцию на перехват клавиши
hookm.KeyDown = OnKeyboardEvent
hookm.KeyUp = OnKeyboardEvent
# Указываем перехватывать события
hookm.HookMouse()
hookm.HookKeyboard()
# Запускаем все действо
PumpMessages()
hCurs1 = win32api.LoadCursor(0, win32con.IDC_CROSS)
win32api.SetCursor(hCurs1)
Отредактировано (Дек. 24, 2009 13:57:01)
Офлайн