Anpassa presentationsformer i Python via Java
Översikt
Den här artikeln förklarar hur du anpassar presentationsformer i Aspose.Slides genom att redigera formgeometri med hjälp av redigeringspunkter och geometriska banor. Den visar hur du arbetar med GeometryPath för att ändra befintliga former, utföra grundläggande redigeringsoperationer på banor, lägga till eller ta bort punkter och tillämpa uppdaterad geometri på en form.
Den demonstrerar också hur du skapar anpassade och sammansatta former, bygger former med rundade hörn, avgör om en formgeometri är sluten, inspekterar formelement och konverterar Java AWT-textkonturer till geometriska banor.
Ändra en form med redigeringspunkter
I PowerPoint kan du använda Edit Points för att ändra en fyrkant:
- Flytta ett hörn inåt eller utåt.
- Justera krökningen vid en punkt.
- Lägg till nya punkter.
Att redigera punkter låter dig ändra enforms kontur eller använda en befintlig form som grund för en ny.
Tips för formredigering

När du redigerar PowerPoint‑former, håll dessa koncept i åtanke:
- En form (eller dess bana) kan vara antingen sluten eller öppen.
- En forms bana består av ankarpunkter som är förenade med segment.
- Ett segment kan vara rakt eller kurvigt. Ankarnpunkter och kontrollhandtag bestämmer dess form.
- Ankarnpunkter finns som hörnpunkter, raka punkter eller släta punkter:
- Vid en hörnpunkt kan intilliggande segment mötas i en vinkel.
- Vid en slät punkt är de två kontrollhandtagen i linje och lika långt från ankarnpunkten.
- Vid en rak punkt är de två kontrollhandtagen i linje men kan ha olika avstånd från ankarnpunkten.
- Att flytta ankarnpunkter eller justera deras handtag ändrar formens kontur.
För att redigera PowerPoint‑former via redigeringspunkter tillhandahåller Aspose.Slides klassen GeometryPath.
- En GeometryPath‑instans representerar en geometrisk bana för objektet GeometryShape.
- För att hämta GeometryPath från GeometryShape-instansen kan du använda metoden GeometryShape.getGeometryPaths.
- För att ange GeometryPath för en form kan du använda dessa metoder: GeometryShape.setGeometryPath för former med en enskild bana och GeometryShape.setGeometryPaths för former med flera banor.
- För att lägga till segment kan du använda metoderna under GeometryPath.
- Genom att använda metoderna GeometryPath.setStroke och GeometryPath.setFillMode kan du ange utseendet för en geometrisk bana.
- Genom att använda metoden GeometryPath.getPathData kan du hämta geometrisk bana för en GeometryShape som en array av bana‑segment.
- För att komma åt ytterligare anpassningsalternativ för formgeometri kan du läsa en java.awt.Shape via dess PathIterator och återuppspela segmenten på en GeometryPath.
Enkla redigeringsoperationer
Använd följande metoder för att redigera en geometrisk bana. Överlagringar som tar emot ett index sätter in ett segment på den nollbaserade positionen i banans segmentarray.
| Operation | Method |
|---|---|
| Lägg till eller sätt in en rak linje. | GeometryPath.lineTo |
| Lägg till eller sätt in en kubisk Bézier‑kurva med två kontrollpunkter och en slutpunkt. | GeometryPath.cubicBezierTo |
| Lägg till eller sätt in en kvadratisk Bézier‑kurva med en kontrollpunkt och en slutpunkt. | GeometryPath.quadraticBezierTo |
| Lägg till en elliptisk båge med angivna dimensioner och vinklar i grader. | GeometryPath.arcTo |
| Stäng den aktuella figuren genom att ansluta dess slutpunkt till startpunkten. | GeometryPath.closeFigure |
| Ange startpunkten för en figur. | GeometryPath.moveTo |
| Ta bort ett segment på ett nollbaserat index. | GeometryPath.removeAt |
Lägg till anpassade punkter till en form
Detta exempel infogar två punkter i en rektangulär form med hjälp av GeometryPath.lineTo och tillämpar den redigerade banan med GeometryShape.setGeometryPath. Koordinaterna är lokala för formen: båda nya punkterna ligger i dess centrum, 100 punkter från vänster och 50 punkter från toppen. Segmentindex 1 och 4 placerar dem på övre och nedre kanterna och drar dessa kanter inåt.
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()

Ta bort punkter från en form
Detta exempel ändrar en hjärtformad kontur genom att ta bort segmentet på nollbaserat index 2 med GeometryPath.removeAt. Genom att tillämpa den modifierade banan med GeometryShape.setGeometryPath uppdateras formens kontur.
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()

Skapa en anpassad form
Detta exempel bygger en femspetsig stjärna med GeometryPath. Växlande yttre och inre radier på 100 respektive 50 punkter definierar spetsarna och nedsänkningarna; ett 72‑graders steg placerar de fem spetsarna jämnt. Banan stängs med GeometryPath.closeFigure och tillämpas på en rektangulär form med GeometryShape.setGeometryPath, vilket ersätter dess kontur.
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()

Skapa en sammansatt anpassad form
Detta exempel definierar två stängda GeometryPath‑objekt för den övre och nedre tredjedelen av en form. Genom att tillämpa båda banorna med GeometryShape.setGeometryPaths skapas en enda sammansatt form med ett gap över dess mellersta tredjedel.
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()

Skapa en anpassad form med kurvade hörn
Detta exempel kombinerar raka segment med GeometryPath.arcTo för att skapa en form med inåtriktade kurvade hörn. Varje hörnstorlek anger bågens bredd och höjd i punkter, och -90‑graders svep ritar en moturs kvartselipse. Den färdiga banan tillämpas med GeometryShape.setGeometryPath och presentationen sparas i PPTX‑format.
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()
Ta reda på om en formgeometri är sluten
Hjälpklassen nedan kontrollerar om varje icke‑tom geometrisk bana avslutas med ett stängningssegment. Den läser GeometryPath.getPathData och jämför det sista segmentets PathSegment.getPathCommand med PathCommandType.Close. Den returnerar False när det inte finns några icke‑tomma banor. Detta kontrollerar det sista kommandet för varje bana; den inspekterar inte varje underfigur inom en bana. Exemplet skriver ut True för en rektangel.
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()
Extrahera och inspektera formelement
Använd GeometryShape.createShapeElements för att inspektera en befintlig form som element som innehåller banpunkter och puntstyper. Kast varje returnerat element till ShapeElement med jpype.JObject för att hämta punkt‑ och typ‑arrayerna via metoderna getPathPoints och getPathTypes. Denna representation är användbar för kontur‑analys eller för att skicka geometri till anpassade ritverktyg.
Exemplet öppnar input.pptx, hittar den första geometriska formen direkt på den första bilden och skriver ut dess bansegment. Använd en presentation som innehåller en form med raka och kurviga segment för att se båda typerna av utdata. Det söker inte inuti grupper.
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()
Arrayerna korrelerar efter index: points[i] är en punkt och types[i] beskriver dess roll. Typ 0 startar en figur, och typ 1 ritar en linje från föregående punkt till den aktuella punkten. Ett kubiskt Bézier‑segment startar vid föregående slutpunkt och använder tre på varandra följande typ‑3‑poster: två kontrollpunkter följda av den nya slutpunkten. Loopen konsumerar dessa tre poster tillsammans och kontrollerar om slutpunkten är sluten.
Punkt‑typer innehåller också flaggor. Maskera med 0x07 för att identifiera segmenttypen, och testa 0x80 separat för att upptäcka en sluten underbana. Till exempel betyder 129 (0x81) en linje‑slutpunkt som stänger en underbana, och 131 (0x83) en Bézier‑slutpunkt som stänger en sådan. Java lagrar dessa flaggor i signerade byte; maskering bevarar de avsedda bitvärdena. Att bara jämföra det råa värdet med 1 eller 3 skulle missa dessa fall. Andra flaggor, såsom streck (0x10) och markör (0x20), förändrar inte bassegmenttypen.
Koordinater och transformationer. Punkter mäts i punkter (1/72 tum), med X som ökar åt höger och Y som ökar nedåt. För en icke‑grupperad form inkluderar de extraherade koordinaterna redan positionen som returneras av getX och getY och speglar dess aktuella bredd och höjd. Till exempel har en orotuerad rektangel på (100, 200) med storlek 120 × 80 konturbundna (100, 200)–(220, 280). Lägg inte till formens position igen. Subtrahera dess X och Y för att få koordinater relativt dess orotuerade ram.
De extraherade punkterna applicerar inte formens rotation, som returneras av getRotation, eller horisontella och vertikala speglingar. För att reproducera den visade konturen, applicera dessa transformationer kring formens centrum. För grupperade former, ta också hänsyn till gruppens koordinatmappning och transformationer; anta inte att de extraherade punkterna är de slutgiltiga renderade bildpunkterna eller applicera en förflyttning eller skalning två gånger om den redan återspeglas i barnets ram.
Inspektion kontra redigering. De extraherade arrayerna beskriver konturen; att ändra dem uppdaterar inte den ursprungliga formen. Välj detta tillvägagångssätt när din analys‑ eller ritkod behöver punkt‑/typ‑arrayer. Använd getGeometryPaths när du behöver geometriska kommandon i formens lokala koordinatsystem eller vill redigera dess geometri. Tillämpa redigerade banor via setGeometryPath eller setGeometryPaths.
Konvertera en Java AWT Shape till GeometryPath
Detta exempel kombinerar en rektangulär kontur med text konverterad till geometri. Konturens setFillMode-metod inaktiverar dess fyllning. En GlyphVector skapar textkonturen i en java.awt.Shape. Dess PathIterator levererar flytt-, linje-, kvadrat-, kubik- och stängningssegment, som exemplet återuppspelar på en GeometryPath.
Texten använder ett 40‑punkts Arial‑typsnitt. Konturen offsetas 20 punkter horisontellt och placeras med sin visuella topp 10 punkter under formens överkant. Textbanan fylls, medan den ursprungliga rektangeln förblir en kontur. Genom att tillämpa båda banorna med GeometryShape.setGeometryPaths skapas en enda form som innehåller rektangeln och texten.
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)
# Hämta geometribanan för formen.
original_path = shape.getGeometryPaths()[0]
original_path.setFillMode(PathFillModeType.None_)
# Skapa en ny grafisk bana med text.
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()
# Konvertera den grafiska banan till en geometribana.
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)
# Tillämpa textbanan tillsammans med den ursprungliga geometribanan.
shape.setGeometryPaths([original_path, text_path])
finally:
presentation.dispose()

FAQ
Vad händer med fyllning och kontur efter att geometrin ersatts?
Stilen förblir på formen; endast konturen ändras. Fyllning och kontur tillämpas automatiskt på den nya geometrin.
Hur roterar jag korrekt en anpassad form tillsammans med dess geometri?
Använd formens setRotation-metod; geometrin roterar med formen eftersom den är bunden till formens eget koordinatsystem.
Kan jag konvertera en anpassad form till en bild för att ”låsa” resultatet?
Ja. Exportera det behövda slide-området eller själva shape till ett rasterformat; detta förenklar vidare arbete med komplexa geometrier.