| Descrizione |
|---|
| Macro per catturare facilmente screenshot di FreeCAD. Versione macro: 1.07 Ultima modifica: 2019-08-05 Versione FreeCAD: Tutti Download: ToolBar Icon Autore: TheMarkster |
| Autore |
| TheMarkster |
| Download |
| ToolBar Icon |
| Link |
| Raccolta di macro Come installare le macro Personalizzare la toolbar |
| Versione macro |
| 1.07 |
| Data ultima modifica |
| 2019-08-05 |
| Versioni di FreeCAD |
| Tutti |
| Scorciatoia |
| Su Windows: Windows Key + Shift + S Su Mac: Command + Shift + 4 |
| Vedere anche |
| Macro Copia la vista 3D negli appunti Macro Screen Wiki |
Usare questa macro per pubblicare facilmente screenshot nel forum di FreeCAD.
Si può aggiungere questa macro alla barra degli strumenti delle macro personalizzate globali per un accesso rapido e semplice.
Quando si pubblica sul forum di FreeCAD, spesso è utile poter includere degli screenshot. Il problema è che si tratta di un compito un po' noioso. Questa macro mira quindi a semplificare un po' il compito.
La macro può acquisire schermate oppure utilizzare schermate esistenti già copiate negli appunti di sistema. Per ignorare l'immagine già presente negli appunti, premere il tasto Shift mentre si richiama la macro. Per utilizzare la macro per acquisire la schermata, regolare le dimensioni e la posizione della finestra di dialogo che si apre, quindi fare clic su OK. Facendo clic su OK, la macro tenterà di acquisire una schermata dell'area dello schermo coperta dalla finestra di dialogo. La finestra di dialogo stessa è semitrasparente, quindi è possibile vederne il contenuto sottostante.
Notare come la finestra di dialogo sia semitrasparente. Verrà catturato solo il contenuto dello schermo sotto la finestra di dialogo.
Dopo aver cliccato su OK, la macro acquisisce lo screenshot e lo salva in un file temporaneo. Viene quindi aperta una finestra di dialogo per l'apertura del file nella posizione del file. È possibile trascinare il file da lì nel forum, nell'area di testo in cui si digita il testo per il post del forum. Annullando la finestra di dialogo, il file temporaneo dello screenshot viene eliminato automaticamente. È anche possibile aprire il file dello screenshot nell'applicazione predefinita installata per l'apertura di file .png (in Windows in genere è Paint). Questo può essere utile se si desidera aggiungere annotazioni allo screenshot o apportare modifiche aggiuntive, come il ritaglio.
Questa è la finestra di dialogo per aprire il file che appare automaticamente dopo aver acquisito lo screenshot. L'immagine può essere trascinata e rilasciata sul forum oppure aperta per un'ulteriore elaborazione nell'applicazione predefinita del sistema per l'apertura dei file PNG. In alternativa, si può fare clic con il pulsante destro del mouse sull'immagine e selezionare Apri con.. per utilizzare un'altra applicazione a scelta.
Se la macro per catturare screenshot non funziona sul sistema, può comunque essere utile per gli screenshot che sono stati catturati con altri strumenti. Copiare semplicemente lo screenshot negli appunti, quindi eseguire la macro. Verrà creato un file temporaneo e verrà aperta la cartella del file in una finestra di dialogo "Apri file". Altri strumenti per catturare screenshot:
La macro supporta i parametri utente, che possono essere impostati tramite Strumenti → Modifica parametri... → Plugin → Snip_Macro
LastX, LastY, LastWidth, LastHeight: posizione e dimensione dell'ultimo utilizzo del riquardo di taglioWindowOpacity (0.85): un valore compreso tra 0,0 (meno opaco) e 1,0 (più opaco)SnipDelay (0.5): tempo (in secondi) di ritardo tra la chiusura del riquardo di ritaglio e il ritaglioDesiredWidth (0): larghezza desiderata (in pixel), ignorata se 0 -- ridimensiona l'immagine alla dimensione desiderata mantenendo le proporzioni correntiScaleFactor (1.0): fattore di scala desiderato (sovrascrive DesiredWidth se ScaleFactor non è 1.0) -- ridimensiona l'immagine in base al fattore di scalaI parametri Last vengono reimpostati dalla macro ogni volta che viene eseguita. In questo modo, tiene traccia di dove posizionare il riquadro di cattura, ovvero l'ultima posizione in cui si trovava quando l'utente ha acquisito uno screenshot.
Il parametro WindowOpacity è l'opacità della casella di ritaglio.
Il parametro SnipDelay può essere regolato per velocizzare un po' le cose, ma se il valore è troppo piccolo, lo screenshot potrebbe includere la casella di ritaglio stessa, perché è necessario un intervallo di tempo per chiudere la finestra di dialogo prima di acquisire lo screenshot.
Il parametro DesiredWidth ridimensiona l'immagine alla larghezza desiderata, a meno che non sia 0 (impostazione predefinita), nel qual caso non viene effettuato alcun ridimensionamento. Ad esempio, se si imposta la larghezza desiderata a 800, si otterranno immagini larghe 800 pixel. L'altezza verrà ridimensionata automaticamente per mantenere le proporzioni correnti. Se l'immagine originale era 1600x1200 e DesiredWidth è 800, l'immagine risultante sarà 800x600.
Il parametro ScaleFactor ridimensiona l'immagine in base al rapporto desiderato, ad esempio 0,5. Il valore predefinito è 1,0, nel qual caso non viene eseguito alcun ridimensionamento. Questo valore sostituisce il parametro DesiredWidth se ScaleFactor non è 1,0.
È possibile ignorare tutti i ridimensionamenti tenendo premuto il tasto Ctrl mentre si fa clic sul pulsante Ok per acquisire lo screenshot.
Icona della barra degli strumenti
Macro_Snip.FCMacro
# -*- coding: utf-8 -*-
"""
***************************************************************************
* Copyright (c) 2019 <TheMarkster> *
* *
* This file is a supplement to the FreeCAD CAx development system. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License (LGPL) *
* as published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This software 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 at http://www.gnu.org/licenses *
* for more details. *
* *
* For more information about the GNU Library General Public License *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307 USA *
* *
***************************************************************************
"""
"""
Snip Macro
This is a macro to make it easier to post screenshots to the FreeCAD forum.
The forum supports a drag and drop interface -- just drag and drop an image to the
textarea where you type in your post. But it still requires many
tedious steps. This macro is to reduce some of those steps.
You should add the macro to your custom macro toolbar to save as many clicks as possible.
The first thing the macro does is to check if there is an image already saved to the
system clipboard, and if so, it uses that one. To bypass the clipboard, press Shift
while invoking the macro.
"""
__title__ = "Snip"
__author__ = "TheMarkster"
__url__ = ""
__Wiki__ = ""
__date__ = "2024.07.23"
__version__ = 1.3
import FreeCAD
from PySide import QtGui,QtCore
import uuid
import time
import tempfile, os, shutil
# class SnipBox(QtGui.QDialog):
# def __init__(self, scale, desired_width):
# QtGui.QDialog.__init__(self)
# self.scale = scale
# self.desired_width = desired_width
#
# self.detailsTextEdit = QtGui.QTextEdit("Details")
# self.Details = QtGui.QPushButton("Details")
# self.Scaling = QtGui.QPushButton("Scaling")
# self.Details.clicked.connect(self.onDetailsClicked)
# self.Scaling.clicked.connect(self.onScalingClicked)
# layout = QtGui.QVBoxLayout()
# layout.addWidget(self.detailsTextEdit)
# layout.addStretch()
# buttons = QtGui.QDialogButtonBox(
# QtGui.QDialogButtonBox.Ok,
# QtCore.Qt.Horizontal, self)
# buttons.accepted.connect(self.accept)
# buttons.rejected.connect(self.reject)
# buttons.addButton(self.Details, QtGui.QDialogButtonBox.ActionRole)
# buttons.addButton(self.Scaling, QtGui.QDialogButtonBox.ActionRole)
# buttons.setCenterButtons(True)
# layout.addWidget(buttons)
# self.setLayout(layout)
# self.detailsTextEdit.setVisible(False)
#
# def setDetailedText(self, txt):
# self.detailsTextEdit.setText(txt)
#
# def setTitle(self, rectwidth, rectheight):
# if self.scale != 1.0:
# out_width = rect.width()*scale_factor
# elif self.desired_width != 0:
# out_width = desired_width
# self.setWindowTitle(f"Snip macro v{__version__} {rectwidth} x {rectheight} output width {out_width}")
#
#
# def onDetailsClicked(self):
# self.detailsTextEdit.setVisible(not self.detailsTextEdit.isVisible())
#
# def onScalingClicked(self):
# pass
#
# def event(self, e): #credit serge_gubenko of stackoverflow for this
# result = QtGui.QDialog.event(self, e)
# self.setMinimumHeight(0)
# self.setMaximumHeight(16777215)
# self.setMinimumWidth(0)
# self.setMaximumWidth(16777215)
# self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
# textEdit = self.findChild(QtGui.QTextEdit)
# if textEdit != None :
# textEdit.setMinimumHeight(0)
# textEdit.setMaximumHeight(16777215)
# textEdit.setMinimumWidth(0)
# textEdit.setMaximumWidth(16777215)
# textEdit.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
# #thanks to mario52 for this
# if result == True:
# try:
# rect = mb.frameGeometry()
# rectwidth = rect.width()
# rectheight = rect.height()
# mb.setTitle(rectwidth,rectheight)
#
# except Exception:
# None
# ##############
# return result
class SnipBox(QtGui.QDialog):
def __init__(self, scale, desired_width):
QtGui.QDialog.__init__(self)
self.pg = FreeCAD.ParamGet("User parameter:Plugins/Snip_Macro")
self.scale = scale
self.desired_width = desired_width
self.detailsTextEdit = QtGui.QTextEdit("Details")
self.Details = QtGui.QPushButton("Details")
self.Scaling = QtGui.QPushButton("Scaling")
self.Details.clicked.connect(self.onDetailsClicked)
self.Scaling.clicked.connect(self.onScalingClicked)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.detailsTextEdit)
layout.addStretch()
# Scaling widgets
self.scaleLabel = QtGui.QLabel("Scale:")
self.scaleSpinBox = QtGui.QDoubleSpinBox()
self.scaleSpinBox.setDecimals(2)
self.scaleSpinBox.setSingleStep(0.1)
self.scaleSpinBox.setValue(self.scale)
self.scaleSpinBox.valueChanged.connect(self.updateScale)
self.fixedWidthLabel = QtGui.QLabel("Fixed Width:")
self.fixedWidthSpinBox = QtGui.QSpinBox()
self.fixedWidthSpinBox.setRange(0, 10000)
self.fixedWidthSpinBox.setValue(self.desired_width)
self.fixedWidthSpinBox.valueChanged.connect(self.updateDesiredWidth)
self.scaleLayout = QtGui.QVBoxLayout()
self.scaleText = QtGui.QLabel("Scale values other than 1.0 will override fixed width setting")
self.scaleLayout.addWidget(self.scaleText)
scaleHBox1 = QtGui.QHBoxLayout()
scaleHBox1.addWidget(self.scaleLabel)
scaleHBox1.addWidget(self.scaleSpinBox)
scaleHBox2 = QtGui.QHBoxLayout()
scaleHBox2.addWidget(self.fixedWidthLabel)
scaleHBox2.addWidget(self.fixedWidthSpinBox)
self.scaleLayout.addLayout(scaleHBox1)
self.scaleLayout.addLayout(scaleHBox2)
self.scaleWidget = QtGui.QWidget()
self.scaleWidget.setLayout(self.scaleLayout)
self.scaleWidget.setVisible(False)
layout.addWidget(self.scaleWidget)
buttons = QtGui.QDialogButtonBox(
QtGui.QDialogButtonBox.Ok,
QtCore.Qt.Horizontal, self)
buttons.accepted.connect(self.accept)
buttons.rejected.connect(self.reject)
buttons.addButton(self.Details, QtGui.QDialogButtonBox.ActionRole)
buttons.addButton(self.Scaling, QtGui.QDialogButtonBox.ActionRole)
buttons.setCenterButtons(True)
layout.addWidget(buttons)
self.setLayout(layout)
self.detailsTextEdit.setVisible(False)
def setDetailedText(self, txt):
self.detailsTextEdit.setText(txt)
def setTitle(self, rectwidth, rectheight):
if self.scale != 1.0:
out_width = rectwidth * self.scale
elif self.desired_width != 0:
out_width = self.desired_width
self.setWindowTitle(f"Snip macro v{__version__} {rectwidth} x {rectheight} output width {out_width}")
def onDetailsClicked(self):
if self.scaleWidget.isVisible():
self.scaleWidget.setVisible(False)
self.detailsTextEdit.setVisible(not self.detailsTextEdit.isVisible())
def onScalingClicked(self):
if self.detailsTextEdit.isVisible():
self.detailsTextEdit.setVisible(False)
self.scaleWidget.setVisible(not self.scaleWidget.isVisible())
def updateScale(self, value):
self.scale = value
self.pg.SetFloat("ScaleFactor", self.scale)
def updateDesiredWidth(self, value):
self.desired_width = value
self.pg.SetInt("DesiredWidth", self.desired_width)
def event(self, e): #credit serge_gubenko of stackoverflow for this
result = QtGui.QDialog.event(self, e)
self.setMinimumHeight(0)
self.setMaximumHeight(16777215)
self.setMinimumWidth(0)
self.setMaximumWidth(16777215)
self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
textEdit = self.findChild(QtGui.QTextEdit)
if textEdit != None :
textEdit.setMinimumHeight(0)
textEdit.setMaximumHeight(16777215)
textEdit.setMinimumWidth(0)
textEdit.setMaximumWidth(16777215)
textEdit.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
#thanks to mario52 for this
if result == True:
try:
rect = mb.frameGeometry()
rectwidth = rect.width()
rectheight = rect.height()
mb.setTitle(rectwidth,rectheight)
except Exception:
None
##############
return result
def get_screen_for_widget(widget):
screen_geometry = widget.geometry()
for screen in QtGui.QApplication.screens():
if screen.geometry().contains(screen_geometry.center()):
return screen
def get_widget_screen_coordinates(widget):
screen = get_screen_for_widget(widget)
widget_geometry = widget.geometry()
screen_geometry = screen.geometry()
return QtCore.QRect(widget_geometry.x() - screen_geometry.x(),
widget_geometry.y() - screen_geometry.y(),
widget_geometry.width(),
widget_geometry.height())
pg = FreeCAD.ParamGet("User parameter:Plugins/Snip_Macro")
#parameters were originally in BaseApp, but should be in Plugins, so relocate if necessary
if FreeCAD.ParamGet("User parameter:BaseApp/Preferences").HasGroup("Snip_Macro"):
deprecated = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Snip_Macro")
pg.SetInt("LastX",deprecated.GetInt("LastX",0))
pg.SetInt("LastY",deprecated.GetInt("LastY",0))
pg.SetInt("LastWidth",deprecated.GetInt("LastWidth",0))
pg.SetInt("LastHeight",deprecated.GetInt("LastHeight",0))
pg.SetFloat("WindowOpacity",deprecated.GetFloat("WindowOpacity",0.85))
pg.SetFloat("SnipDelay",deprecated.GetFloat("SnipDelay",0.5))
FreeCAD.ParamGet("User parameter:BaseApp/Preferences").RemGroup("Snip_Macro")
desired_width = pg.GetInt("DesiredWidth",0) #used for scaling to desired width, maintaining aspect ratio
pg.SetInt("DesiredWidth", desired_width)
scale_factor = pg.GetFloat("ScaleFactor", 1.0) #scale by scale factor instead of desired width
pg.SetFloat("ScaleFactor", scale_factor)
skipClipboard = False
modifiers = QtGui.QApplication.keyboardModifiers()
if modifiers == QtCore.Qt.ShiftModifier:
skipClipboard = True
userCanceled = False
fname = "Snip macro screenshot-"+str(uuid.uuid4())[:6]+".png"
image = None
if not skipClipboard:
clip = QtGui.QClipboard()
image = clip.image(QtGui.QClipboard.Clipboard)
if not image:
#use our own screen grabber
mb = SnipBox(scale_factor, desired_width)
details = """
Move and resize this box to cover the part of the screen you wish to grab.
If it succeeds an open file dialog will appear. Drag and drop the file
from the open file dialog to the forum. The file will be deleted after
you close the dialog.
If this fails you can still use this macro to handle screenshots you
copied to the clipboard using other tools:
Windows snip tool: Window Key + Shift + S
Mac snip tool: Command + Shift + 4
Linux: gnome-screenshot utility
If the macro finds there is already an image copied to the clipboard
it uses that image instead of bringing up this dialog. Press Shift
while invoking this macro to bypass the clipboard. Alternatively,
you can clear the image from the clipboard by copying some text to it.
The Open button will open the file in the system
default application for handling png files, e.g. Paint in windows. This
can be useful if you wish to annotate the screenshot. But most of the
time you will simply want to drag and drop the file to the forum, then
Cancel to close the open file dialog afterwards.
If you wish to open the screenshot file with another application, right-click
the file and select open with... option or drag/drop to that other application.
User Parameters: These can be accessed via Tools menu -> Edit Parameters in
Plugins -> Snip_Macro:
LastX, LastY, LastWidth, LastHeight -- location and size of snip box last use
WindowOpacity (0.85) -- value between 0.0 (less opaque) and 1.0 (more opaque)
SnipDelay (0.5) -- time (in seconds) delay between snip box close and snip
DesiredWidth -- image will be scaled to this width (unless it is 0) maintaining
current aspect ratio.
ScaleFactor -- float value, e.g. 0.5 -- image will be scaled to that scale factor.
Note: ScaleFactor (if not 1.0) will take precedence over DesiredWidth
Hold down Ctrl key to ignore scaling.
The SnipDelay parameter can be adjusted to speed things up a bit, but if it
is too small the screenshot taken might include the snip box itself because
we need to wait for it to close before taking the screenshot.
"""
# mb.setWindowTitle("Snip macro v"+str(__version__))
mb.setDetailedText(details)
if pg.GetFloat("WindowOpacity",0.85) == 0.85:
pg.SetFloat("WindowOpacity",0.85)
mb.setWindowOpacity(pg.GetFloat("WindowOpacity",0.85))
lastX = pg.GetInt("LastX",0)
lastY = pg.GetInt("LastY",0)
lastWidth = pg.GetInt("LastWidth",100)
lastHeight = pg.GetInt("LastHeight",100)
mb.setGeometry(lastX, lastY, lastWidth, lastHeight)
mb.resize(lastWidth, lastHeight)
mb.setWindowFlags(QtCore.Qt.Tool)
result = mb.exec_()
if not result:
userCanceled = True
if not userCanceled:
clientRect = mb.geometry()
scale_factor = mb.scale
desired_width = mb.desired_width
rect = get_widget_screen_coordinates(mb)
diff = rect.height()-clientRect.height()
pg.SetInt("LastX", rect.x())
pg.SetInt("LastY", rect.y())
pg.SetInt("LastWidth", rect.width())
pg.SetInt("LastHeight", rect.height()-diff)
QtGui.QApplication.processEvents()
snipDelay = pg.GetFloat("SnipDelay", 0.5)
if snipDelay == 0.5:
pg.SetFloat("SnipDelay", 0.5)
time.sleep(snipDelay) #give time for dialog to close before taking screenshot
QtGui.QApplication.processEvents()
if hasattr(QtGui.QApplication,"primaryScreen"):
#screen = QtGui.QApplication.primaryScreen()
screen = get_screen_for_widget(mb)
image = screen.grabWindow(0,rect.x(),rect.y(),rect.width(),rect.height()).toImage()
else:
long_qdesktop_id = QtGui.QApplication.desktop().winId()
image = QtGui.QPixmap.grabWindow(long_qdesktop_id, rect.x(), rect.y(), rect.width(), rect.height()).toImage()
if not image:
raise Exception("Snip Macro Error: Unable to grab screen image\n")
modifiers = QtGui.QApplication.keyboardModifiers()
skipScaling = False
if modifiers == QtCore.Qt.ControlModifier:
skipScaling = True
if not skipScaling:
if scale_factor != 1.0:
image = image.smoothScaled(rect.width()*scale_factor, rect.height()*scale_factor)
elif desired_width != 0:
image = image.smoothScaled(desired_width, rect.height()*float(desired_width)/float(rect.width()))
if not userCanceled:
dirPath = tempfile.mkdtemp()
filePath = dirPath + os.path.sep + fname
image.save(filePath)
fileName = QtGui.QFileDialog.getOpenFileName(QtGui.QApplication.activeWindow(),
"Drag the image to the forum, then Cancel will delete the temporary file", dirPath, "PNG (*.png)")
if fileName[0]: #user selected Open or double-clicked file
import subprocess, os, platform
if platform.system() == 'Darwin': # macOS
subprocess.call(('open', fileName[0]))
elif platform.system() == 'Windows': # Windows
os.startfile(fileName[0])
else: # linux variants
subprocess.call(('xdg-open', fileName[0]))
QtGui.QApplication.processEvents() #allow some time for file to open before deleting temp folder and contents
time.sleep(1)
QtGui.QApplication.processEvents()
shutil.rmtree(dirPath)
La discussione sul forum Snip macro