Prezentációs alakzatok testreszabása Pythonban Java-n keresztül
Áttekintés
Ez a cikk bemutatja, hogyan lehet testreszabni a prezentáció alakzatait az Aspose.Slides segítségével a forma geometria szerkesztésével szerkesztőpontok és geometriai útvonalak segítségével. Megmutatja, hogyan lehet a GeometryPath használatával módosítani meglévő alakzatokat, alapvető útvonal-szerkesztési műveleteket végrehajtani, pontokat hozzáadni vagy eltávolítani, és az frissített geometriát visszaalkalmazni egy alakzatra.
Emellett bemutatja, hogyan lehet egyedi és összetett alakzatokat létrehozni, ívelt sarkokkal ellátott alakzatokat építeni, meghatározni, hogy egy forma geometria zárt‑e, vizsgálni a formaelemeket, és a Java AWT szöveg körvonalait geometriai útvonalakká alakítani.
Alakzat módosítása szerkesztőpontokkal
PowerPointban a Szerkesztőpontok segítségével egy négyzetet módosíthat:
- Egy sarkot be‑ vagy kifelé mozgathat.
- Egy pont ívének görbületét állíthatja.
- Új pontokat adhat hozzá.
A pontok szerkesztése lehetővé teszi egy alakzat körvonalának módosítását, vagy egy meglévő alakzat alapjának felhasználását egy új létrehozásához.
Alakzat szerkesztési tippek

PowerPoint‑alakzatok szerkesztésekor tartsa szem előtt a következőket:
- Egy alakzat (vagy annak útvonala) lehet zárt vagy nyitott.
- Az alakzat útvonala horgonypontokból áll, amelyeket szegmensek kötnek össze.
- Egy szegmens lehet egyenes vagy íves. A horgonypontok és a vezérlő fogantyúk határozzák meg alakját.
- A horgonypontok három típusúak: sarokpont, egyenes pont vagy sima pont:
- Sarokpontnál a szomszédos szegmensek szöget zárhatnak be.
- Simapontnál a két vezérlő fogantyú egy vonalban van, és azonos távolságra helyezkedik el a horgonyponttól.
- Egyenes pontnál a két vezérlő fogantyú egy vonalban van, de távolságuk eltérhet a horgonyponttól.
- A horgonypontok mozgatása vagy fogantyúik módosítása megváltoztatja az alakzat körvonalát.
PowerPoint‑alakzatok szerkesztéséhez szerkesztőpontokkal a Aspose.Slides a GeometryPath osztályt biztosítja.
- Egy GeometryPath példány a GeometryShape objektum geometriai útvonalát képviseli.
- A GeometryPath lekéréséhez a GeometryShape példányból a GeometryShape.getGeometryPaths metódust használhatja.
- A GeometryPath beállításához egy alakzatra használja a GeometryShape.setGeometryPath metódust egyetlen útvonalú alakzatoknál, illetve a GeometryShape.setGeometryPaths metódust több útvonalú alakzatoknál.
- Szegmensek hozzáadásához a GeometryPath alatti metódusokat használhatja.
- A GeometryPath.setStroke és a GeometryPath.setFillMode metódusokkal beállíthatja a geometriai útvonal megjelenését.
- A GeometryPath.getPathData metódus segítségével egy GeometryShape útvonaladatait tömbként kaphatja meg.
- További forma‑geometria testreszabási lehetőségekhez a java.awt.Shape objektumot a PathIterator segítségével olvashatja, és a szegmenseket egy GeometryPath‑re “újrajátszhatja”.
Egyszerű szerkesztési műveletek
Használja az alábbi metódusokat egy geometriai útvonal szerkesztéséhez. Az indexet elfogadó felülírások a szegmens‑tömbben a megadott nullán‑induló pozícióba szúrják be a szegmenst.
| Művelet | Metódus |
|---|---|
| Egyenes vonal hozzáadása vagy beszúrása. | GeometryPath.lineTo |
| Két vezérlőponttal és egy végponttal rendelkező kúp Bézier‑görbe hozzáadása vagy beszúrása. | GeometryPath.cubicBezierTo |
| Egyetlen vezérlőponttal és egy végponttal rendelkező kvadratikus Bézier‑görbe hozzáadása vagy beszúrása. | GeometryPath.quadraticBezierTo |
| Elliptikus ív hozzáadása a megadott méretekkel és fokokban kifejezett szögekkel. | GeometryPath.arcTo |
| A jelenlegi alakzat lezárása az végpont és a kezdőpont összekötésével. | GeometryPath.closeFigure |
| Az alakzat kezdőpontjának beállítása. | GeometryPath.moveTo |
| Szegmens eltávolítása nullán‑induló index szerint. | GeometryPath.removeAt |
Egyedi pontok hozzáadása egy alakzathoz
Ez a példa két pontot szúr be egy téglalapba a GeometryPath.lineTo használatával, majd a szerkesztett útvonalat a GeometryShape.setGeometryPath‑vel alkalmazza. A koordináták a forma lokális rendszere szerint értendők: mindkét új pont a középpontban helyezkedik el, 100 pontbalra és 50 pont lejjebb. Az 1‑es és 4‑es szegmens‑indexek a pontokat a felső és alsó élre teszik, ezáltal az éleket befelé húzva.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100)
geometry_path = shape.getGeometryPaths()[0]
geometry_path.lineTo(100, 50, 1)
geometry_path.lineTo(100, 50, 4)
shape.setGeometryPath(geometry_path)
finally:
presentation.dispose()

Pontok eltávolítása egy alakzatról
Ez a példa egy szív alakú körvonalat módosít azzal, hogy a GeometryPath.removeAt segítségével eltávolítja a 2‑es nullán‑induló indexű szegmenst. A módosított útvonal GeometryShape.setGeometryPath‑vel való alkalmazása frissíti az alakzat kontúrt.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Heart, 100, 100, 300, 300)
geometry_path = shape.getGeometryPaths()[0]
geometry_path.removeAt(2)
shape.setGeometryPath(geometry_path)
finally:
presentation.dispose()

Egyedi alakzat létrehozása
Ez a példa ötágú csillagot épít a GeometryPath‑vel. A 100 és 50 pont közötti váltakozó külső‑ és belső‑sugár határozza meg a csúcsokat és a bemetsüléseket; a 72 fokos lépés egyenlően osztja el az öt csúcsot. Az útvonal a GeometryPath.closeFigure‑vel záródik, és a GeometryShape.setGeometryPath‑vel egy téglalapra alkalmazva felülírja annak körvonalát.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, GeometryPath
import math
points = []
outer_radius = 100
inner_radius = 50
angle_step = 72
for angle in range(-90, 270, angle_step):
radians = math.radians(angle)
x = outer_radius * math.cos(radians)
y = outer_radius * math.sin(radians)
points.append((x + outer_radius, y + outer_radius))
radians = math.radians(angle + angle_step / 2)
x = inner_radius * math.cos(radians)
y = inner_radius * math.sin(radians)
points.append((x + outer_radius, y + outer_radius))
star_path = GeometryPath()
star_path.moveTo(*points[0])
for point in points[1:]:
star_path.lineTo(*point)
star_path.closeFigure()
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, outer_radius * 2, outer_radius * 2)
shape.setGeometryPath(star_path)
finally:
presentation.dispose()

Összetett egyedi alakzat létrehozása
Ez a példa két zárt GeometryPath objektumot definiál a forma felső és alsó harmadához. Mindkét útvonal a GeometryShape.setGeometryPaths‑vel való alkalmazásával egyetlen összetett alakzatot hoz létre, amelynek középső harmada üres marad.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, GeometryPath
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100)
top_path = GeometryPath()
top_path.moveTo(0, 0)
top_path.lineTo(shape.getWidth(), 0)
top_path.lineTo(shape.getWidth(), shape.getHeight() / 3)
top_path.lineTo(0, shape.getHeight() / 3)
top_path.closeFigure()
bottom_path = GeometryPath()
bottom_path.moveTo(0, shape.getHeight() / 3 * 2)
bottom_path.lineTo(shape.getWidth(), shape.getHeight() / 3 * 2)
bottom_path.lineTo(shape.getWidth(), shape.getHeight())
bottom_path.lineTo(0, shape.getHeight())
bottom_path.closeFigure()
shape.setGeometryPaths([top_path, bottom_path])
finally:
presentation.dispose()

Egyedi alakzat ívelt sarkokkal
Ez a példa egyenes szegmenseket kombinál a GeometryPath.arcTo‑val, hogy egy belső‑görbületű sarkokkal rendelkező alakzatot kapjon. Minden sarok mérete meghatározza az ív szélességét és magasságát pontban, a –90 fokos ív pedig egy óramutatóval ellentétes negyed‑ellipszist rajzol. A kész útvonalat a GeometryShape.setGeometryPath‑vel alkalmazza, és a bemutatót PPTX formátumban menti.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, GeometryPath, SaveFormat
shape_x = 20
shape_y = 20
shape_width = 300
shape_height = 200
left_top_size = 50
right_top_size = 20
right_bottom_size = 40
left_bottom_size = 10
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Custom, shape_x, shape_y, shape_width, shape_height)
geometry_path = GeometryPath()
geometry_path.moveTo(left_top_size, 0)
geometry_path.lineTo(shape_width - right_top_size, 0)
geometry_path.arcTo(right_top_size, right_top_size, 180, -90)
geometry_path.lineTo(shape_width, shape_height - right_bottom_size)
geometry_path.arcTo(right_bottom_size, right_bottom_size, -90, -90)
geometry_path.lineTo(left_bottom_size, shape_height)
geometry_path.arcTo(left_bottom_size, left_bottom_size, 0, -90)
geometry_path.lineTo(0, left_top_size)
geometry_path.arcTo(left_top_size, left_top_size, 90, -90)
geometry_path.closeFigure()
shape.setGeometryPath(geometry_path)
presentation.save("output.pptx", SaveFormat.Pptx)
finally:
presentation.dispose()
Megszerzés, hogy egy alakzat geometria zárt‑e
Az alábbi segédfüggvény ellenőrzi, hogy minden nem üres geometriai útvonal záró szegmensekkel végződik‑e. A GeometryPath.getPathData‑t olvassa, majd a végső szegmens PathSegment.getPathCommand értékét összehasonlítja a PathCommandType.Close‑val. Ha nincs nem üres útvonal, False‑t ad vissza. A függvény az egyes útvonalak végső parancsát ellenőrzi; nem elemzi a pálya minden alalakzatát. A példa a négyzet esetén True‑t ír ki.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, PathCommandType
def is_geometry_closed(geometry_shape):
has_nonempty_path = False
for geometry_path in geometry_shape.getGeometryPaths():
path_data = geometry_path.getPathData()
if len(path_data) == 0:
continue
last_segment = path_data[-1]
has_nonempty_path = True
if last_segment.getPathCommand() != PathCommandType.Close:
return False
return has_nonempty_path
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 200, 100)
closed = is_geometry_closed(shape)
print(closed)
finally:
presentation.dispose()
Alakzat elemeinek kinyerése és vizsgálata
Használja a GeometryShape.createShapeElements metódust, hogy egy meglévő alakzatot elemekkel vizsgáljon, amelyek útvonallépéseket és ponttípusokat tartalmaznak. Minden visszakapott elemet ShapeElement típusra castoljon jpype.JObject‑kel, majd a getPathPoints és a getPathTypes metódusok segítségével szerezze be a pont‑ és típus‑tömböket. Ez a reprezentáció hasznos kontúr‑elemzéshez vagy a geometria saját rajzolóeszközökbe történő továbbításához.
A példa megnyit egy input.pptx fájlt, megtalálja az első geometriai alakzatot az első dián, és kiírja annak szegmenseit. Használjon olyan bemutatót, amelynek alakzata egyenes és ívelt szegmenseket is tartalmaz, hogy mindkét kimenetet lássa. Csoportokon belül nem keres.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, GeometryShape, ShapeElement
presentation = Presentation("input.pptx")
try:
slide = presentation.getSlides().get_Item(0)
shape = None
for candidate in slide.getShapes():
if isinstance(candidate, GeometryShape):
shape = candidate
break
if shape is None:
print("No geometry shape found on the first slide.")
else:
for element in shape.createShapeElements():
shape_element = jpype.JObject(element, ShapeElement)
points = shape_element.getPathPoints()
types = shape_element.getPathTypes()
print("Shape element:")
i = 0
while i < len(points):
point_type = types[i] & 0x07 # Keep the segment type, excluding flags.
if point_type == 0:
print(f"Start figure at {points[i]}")
elif point_type == 1:
print(f"Line to {points[i]}")
elif point_type == 3:
print(f"Cubic Bezier: controls {points[i]}, {points[i + 1]}; end {points[i + 2]}")
i += 2 # Consume both control points and the endpoint.
if types[i] & 0x80:
print("Close subpath back to its starting point.")
i += 1
finally:
presentation.dispose()
A tömbök index szerint egyeznek: points[i] egy pont, types[i] leírja a szerepét. Az 0 típusú elem új alakzatot indít, az 1 típusú elem egy vonalat rajzol az előző pontból a jelenlegi pontba. Egy köb‑Bézier szegmens az előző végpontból indul, és három egymást követő, 3‑as típusú bejegyzést használ: két vezérlőpontot, majd az új végpontot. A ciklus ezeket a három bejegyzést egyszerre fogyasztja, és a végpont zártságát ellenőrzi.
A ponttípusok flag‑eket is tartalmaznak. A 0x07 maskával azonosítható a szegmens típusa, az 0x80 flag külön tesztelhető a zárt alútvonal felismerésére. Például a 129 (0x81) egy vonal‑végpontot jelent, amely zár egy alútvonalat, a 131 (0x83) pedig egy Bézier‑végpontot, amely zár egyet. A Java ezeket a flag‑eket előjeles bájtokban tárolja; a maskolás megőrzi a kívánt bitértékeket. A nyers érték csak 1‑gyel vagy 3‑mal való összehasonlítása kihagyná ezeket az eseteket. Más flag‑ek, például a szaggatás (0x10) vagy a marker (0x20), nem változtatják az alap szegmens típust.
Koordináták és transzformációk. A pontok pontban (1/72 hüvelyk) vannak megadva, az X jobbra, az Y lefelé növekszik. Egy nem csoportosított alakzatra a kinyert koordináták már tartalmazzák a getX és getY által visszaadott pozíciót, valamint a jelenlegi szélességet és magasságot. Például egy nem elforgatott téglalap a (100, 200)‑n, 120 × 80 mérettel a kontúr határa (100, 200)–(220, 280). Ne adja hozzá újra az alakzat pozícióját; vonja ki az X‑et és Y‑t a lokális koordinátákhoz.
A kinyert pontok nem tartalmazzák az alakzat forgását, amelyet a getRotation ad, illetve a vízszintes és függőleges tükrözést. A megjelenített kontúr reprodukálásához ezekkel a transzformációkkal kell eljárni a forma középpontja körül. Csoportos alakzatok esetén vegye figyelembe a csoport koordináta‑leképezését és transzformációit is; ne feltételezze, hogy a kinyert pontok a végleges diá-koordináták, és ne alkalmazzon egy fordítást vagy méretezést kétszer, ha már a gyermek keretben megjelennek.
Vizsgálat vs. szerkesztés. A kinyert tömbök a kontúrt írják le; ezek módosítása nem frissíti az eredeti alakzatot. Ezt a módszert akkor válassza, ha a pont/típus tömbökre épülő elemzésre vagy rajzoló programra van szükség. Használja a getGeometryPaths‑t, ha a geometriai parancsokra a forma lokális koordináta‑rendszerében van szüksége, vagy ha a geometria szerkesztése a cél. Szerkesztett útvonalak alkalmazásához használja a setGeometryPath vagy a setGeometryPaths metódusokat.
Java AWT Shape konvertálása GeometryPath‑vé
Ez a példa egy téglalap körvonalát kombinálja a geometriává konvertált szöveggel. A körvonal setFillMode metódusa kikapcsolja a kitöltést. Egy GlyphVector létrehozza a szöveg körvonalát egy java.awt.Shape objektumban. A PathIterator mozgás, vonal, kvadratikus, kúp‑Bézier és záró szegmenseket szolgáltat, amelyeket a példa egy GeometryPath‑re újrajátssza.
A szöveg 40‑pont Arial betűtípussal jelenik meg. A körvonal 20 ponttal vízszintesen eltolódik, a vizuális teteje pedig 10 ponttal az alakzat felső szélétől lejjebb helyezkedik el. A szöveg útvonal kitöltött, míg az eredeti téglalap csak körvonal marad. Mindkét útvonal a GeometryShape.setGeometryPaths‑vel való alkalmazásával egyetlen alakzattá alakul, amely a téglalapot és a szöveget egyaránt tartalmazza.
import jpype
import asposeslides
if not jpype.isJVMStarted():
jpype.startJVM()
from asposeslides.api import Presentation, ShapeType, GeometryPath, PathFillModeType
from java.awt import Font
from java.awt.geom import PathIterator
from java.awt.image import BufferedImage
presentation = Presentation()
try:
slide = presentation.getSlides().get_Item(0)
shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 100, 100, 300, 100)
# A forma geometriai útvonalának lekérése.
original_path = shape.getGeometryPaths()[0]
original_path.setFillMode(PathFillModeType.None_)
# Új grafikus útvonal létrehozása szöveggel.
font = Font("Arial", Font.PLAIN, 40)
text = "Text in shape"
image = BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB)
graphics = image.createGraphics()
try:
font_context = graphics.getFontRenderContext()
glyph_vector = font.createGlyphVector(font_context, text)
text_bounds = glyph_vector.getVisualBounds()
baseline = -text_bounds.getY() + 10
graphics_path = glyph_vector.getOutline(20.0, baseline)
finally:
graphics.dispose()
# A grafikus útvonal átalakítása geometriai útvonallá.
text_path = GeometryPath()
path_iterator = graphics_path.getPathIterator(None)
points = jpype.JArray(jpype.JFloat)(6)
while not path_iterator.isDone():
segment_type = path_iterator.currentSegment(points)
if segment_type == PathIterator.SEG_MOVETO:
text_path.moveTo(points[0], points[1])
elif segment_type == PathIterator.SEG_LINETO:
text_path.lineTo(points[0], points[1])
elif segment_type == PathIterator.SEG_QUADTO:
text_path.quadraticBezierTo(points[0], points[1], points[2], points[3])
elif segment_type == PathIterator.SEG_CUBICTO:
text_path.cubicBezierTo(points[0], points[1], points[2], points[3], points[4], points[5])
elif segment_type == PathIterator.SEG_CLOSE:
text_path.closeFigure()
path_iterator.next()
text_path.setFillMode(PathFillModeType.Normal)
# Apply the text path together with the original geometry path.
shape.setGeometryPaths([original_path, text_path])
finally:
presentation.dispose()

GYIK
Mi történik a kitöltéssel és a körvonallal a geometria cseréje után?
A stílus az alakzaton marad; csak a kontúr változik. A kitöltés és a körvonal automatikusan a új geometriára kerül.
Hogyan forgathatom helyesen az egyedi alakzatot a geometriai adatokkal együtt?
Használja az alakzat setRotation metódusát; a geometria az alakzattal együtt forgik, mivel a forma saját koordináta‑rendszeréhez van kötve.
Átalakíthatom‑e az egyedi alakzatot képpé a „lezáráshoz”?
Igen. Exportálja a kívánt slide területet vagy a shape‑t raster formátumba; ez egyszerűsíti a komplex geometriákkal való további munkát.